Nginx + SSL 免费证书申请与自动续期完整教程(acme.sh)

📅 2026年05月19日 · 技术

概述

在现代 Web 架构中,HTTPS 已不再是可选项,而是强制性的安全标准。Google Chrome 等主流浏览器已明确将 HTTP 页面标记为"不安全",而 Let's Encrypt 等免费证书颁发机构则让 SSL 证书的获取成本降到了零。然而,手动申请证书每三个月续期一次显然不符合运维效率要求。

本文将带你从零开始完成以下目标:

💡 前置条件: 你需要拥有一台公网服务器(本文以 Ubuntu 22.04/24.04 LTS 为例),一个已解析到该服务器的域名,以及服务器的 root 或 sudo 权限。

一、安装 Nginx

Nginx 是一款轻量级但性能卓越的 HTTP 服务器和反向代理服务器,由俄罗斯开发者 Igor Sysoev 创建,因其高并发处理能力和内存效率而广受好评。我们首先在服务器上安装它。

1.1 更新系统并安装

# 更新软件包索引
sudo apt update

# 升级现有软件包(推荐)
sudo apt upgrade -y

# 安装 Nginx
sudo apt install nginx -y

1.2 验证安装

sudo systemctl status nginx

如果输出中包含 active (running),说明 Nginx 已成功启动。你也可以直接访问服务器 IP 地址,看到 Nginx 默认欢迎页面即表示安装成功。

✅ 提示: 如果 Nginx 未启动,检查是否被防火墙拦截(80/443 端口),或使用 sudo systemctl enable nginx && sudo systemctl start nginx 手动启用。

二、安装 acme.sh

acme.sh 是一个纯 Shell 编写的 ACME 协议客户端,支持 Let's Encrypt、ZeroSSL、Buypass、Google Trust Services 等多种证书颁发机构。它的最大优势是完全自动化——申请、安装、续期一条龙。

2.1 安装依赖

sudo apt install socat curl wget -y

socat 用于处理 SSL 验证过程中的网络通信,curlwget 是下载和网络请求工具。

2.2 安装 acme.sh

curl https://get.acme.sh | sh -s [email protected]

请务必将 [email protected] 替换为你自己的邮箱地址,用于接收证书过期提醒等重要通知。

2.3 加载环境变量

source ~/.bashrc

或者重新登录 SSH 会话,使 acme.sh 命令生效。

三、创建网站配置文件

3.1 新建 Nginx 站点配置

/etc/nginx/sites-available/ 目录下为你的域名创建配置文件:

sudo nano /etc/nginx/sites-available/example.com

example.com 替换为你的实际域名。填入以下初始配置(HTTP 模式,后续升级为 HTTPS):

server {
    listen 80;
    server_name example.com;  # 替换为你的域名

    root /var/www/example.com;  # 替换为你的域名
    index index.html index.htm;

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

3.2 创建网站目录

# 创建网站根目录
sudo mkdir -p /var/www/example.com

# 设置权限为 Nginx 用户
sudo chown -R www-data:www-data /var/www/example.com

3.3 启用站点

# 创建软链接
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# 测试配置
sudo nginx -t

# 重启 Nginx
sudo systemctl restart nginx

如果 nginx -t 输出类似以下内容,说明配置正确:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

四、申请 SSL 证书

4.1 设置默认 CA 为 Let's Encrypt

~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

4.2 申请证书

使用 --webroot 模式验证域名所有权,acme.sh 会在网站根目录下创建临时验证文件:

~/.acme.sh/acme.sh --issue -d example.com --webroot /var/www/example.com

申请成功后,你会看到证书存放路径:

Your cert is in: /root/.acme.sh/example.com_ecc/example.com.cer
Your cert key is in: /root/.acme.sh/example.com_ecc/example.com.key
The intermediate CA cert is in: /root/.acme.sh/example.com_ecc/ca.cer
And the full-chain cert is in: /root/.acme.sh/example.com_ecc/fullchain.cer
⚠️ 注意: 免费证书不支持泛域名(通配符)申请。你需要为每个具体的子域名单独申请证书。例如 www.example.comapi.example.com 需要分别申请。

如果需要为内网穿透(如 Frp)的子域名申请证书,同样需要填写完整域名。

五、安装证书到 Nginx

5.1 创建证书存放目录

sudo mkdir -p /etc/nginx/ssl/example.com

5.2 安装证书

~/.acme.sh/acme.sh --install-cert -d example.com \
    --key-file /etc/nginx/ssl/example.com/private.key \
    --fullchain-file /etc/nginx/ssl/example.com/cert.pem \
    --reloadcmd "sudo systemctl reload nginx"

参数说明:

六、配置 Nginx 使用 HTTPS

有了证书之后,我们更新 Nginx 配置,启用 HTTPS 并做 HTTP 自动跳转。

sudo nano /etc/nginx/sites-available/example.com

将文件内容全部替换为以下配置(注意替换域名):

# HTTP → HTTPS 重定向
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

# HTTPS 服务器块
server {
    listen 443 ssl;
    server_name example.com;

    # SSL 证书
    ssl_certificate /etc/nginx/ssl/example.com/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/private.key;

    # 安全协议与加密套件
    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:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS(强制 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000" always;

    # 网站根目录
    root /var/www/example.com;
    index index.html index.htm;

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

    # SSL 性能优化
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
}

6.1 应用配置

sudo nginx -t
sudo systemctl restart nginx

此时访问 https://example.com 应能看到页面,且浏览器地址栏显示安全锁标识。如果看到 403 Forbidden,说明 HTTPS 已正常工作,只是网站根目录还没有内容文件——这属于正常情况。

七、自动续期配置

acme.sh 的最大优势在于自动化。安装完成后,它会自动在系统 crontab 中注册定时任务:

crontab -l

你应当能看到类似以下的任务:

0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

这意味着 acme.sh 会每天检查证书有效期,当距离过期不足 30 天时自动续期,续期后自动执行 --reloadcmd 中的 sudo systemctl reload nginx 使新证书生效。整个过程完全无需人工介入。

✅ 确认自动续期: 你可以手动测试续期流程是否正常:~/.acme.sh/acme.sh --cron --debug,观察输出中是否包含续期和 reload 操作。

八、反向代理配置

大多数场景下,Nginx 并非直接提供静态文件,而是作为反向代理将请求转发到后端服务(如 Node.js、Python、Java 等应用)。下面是典型的反向代理配置:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/private.key;

    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;
    ssl_prefer_server_ciphers off;

    add_header Strict-Transport-Security "max-age=31536000" always;

    # 反向代理
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 将请求转发到后端服务(修改为你的实际端口)
        proxy_pass http://127.0.0.1:8848;

        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # 缓冲区设置
        proxy_buffer_size 4k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;
    }

    # Gzip 压缩(可选)
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_min_length 1000;
    gzip_comp_level 6;

    # SSL 性能
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # OCSP
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
}
🔧 提示: proxy_pass http://127.0.0.1:8848; 中的端口号要根据你的实际后端服务进行修改。例如 Node.js 应用运行在 3000 端口,则改为 proxy_pass http://127.0.0.1:3000;

九、进阶:多服务与负载均衡

9.1 多路径转发

当同一域名下存在多个后端服务时,可以通过不同的 location 路径分发:

# API 服务
location /api/ {
    proxy_pass http://127.0.0.1:8848/;
}

# 管理后台
location /admin/ {
    proxy_pass http://127.0.0.1:8849/;
}

# 静态文件
location /static/ {
    alias /var/www/static/;
    expires 7d;
}

9.2 负载均衡

upstream backend {
    server 127.0.0.1:8848;
    server 127.0.0.1:8849;
    server 127.0.0.1:8850;
}

location / {
    proxy_pass http://backend;
}

十、重要提示与故障排查

10.1 DNS 解析检查

使用 ping example.comdig example.com 确认域名已正确解析到服务器 IP。

10.2 端口开放

确保服务器的 80 和 443 端口对公网可访问。云服务器通常需要在安全组/防火墙中放行相应端口。

10.3 查看日志

# Nginx 错误日志
sudo tail -f /var/log/nginx/error.log

# 访问日志
sudo tail -f /var/log/nginx/access.log

10.4 常见问题

十一、总结

至此,你已经完成了一套完整的 Nginx + SSL 免费证书配置流程。从安装 Nginx 开始,到使用 acme.sh 自动化申请 Let's Encrypt 证书,配置 HTTPS 反向代理,再到自动续期,完全实现零成本、零人工干预的 HTTPS 运维方案。

这套方案适用于个人博客、企业官网、API 服务以及其他任何需要 HTTPS 加密的 Web 场景。配合 Nginx 强大的反向代理能力,你可以轻松管理多个后端服务,实现统一的安全入口。

参考来源

🔧 在线开发者工具 — JSON格式化 · Base64 · UUID生成 · 正则测试 等80+免费工具