acme证书

acme证书

简述

  1. 早期我使用的 nginx+aliyun 免费1年的证书
  2. 之后短暂使用过 aliyun 3月免费证书 + 手动续期
  3. 然后采用 traefik + acme 申请免费证书,但是因为 traefik 不支持静态网站,还得再搭配一个 Nginx;
  4. 前几天偶然看别人提起 nginx 支持 acme了,于是立刻更换;

项目 https://github.com/nginx/nginx-acme

文档 https://nginx.org/en/docs/http/ngx_http_acme_module.html

要求和限制

  1. 目前只支持 HTTP-01 挑战
  2. 需要 rust 编译环境
  3. 最低版本要求: NGINX 1.25.1

实例

简述

  1. 准备 rust 编译环境
  2. 安装基础依赖, 主要是 c 库
  3. nginx 编译出一个 so 库
  4. 将这个 so 库打包进原生nginx docker镜像
  5. 配置 nginx + 运行 docker

docker只是可选项, nginx很早前就支持加载动态库了;


# 安装 Rust 工具链 (cargo 和 rustc)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

wget https://nginx.org/download/nginx-1.29.2.tar.gz

sudo apt install gcc libpcre2-dev libssl-dev zlib1g-dev
sudo apt install clang libc6-dev
sudo apt install -y pkg-config libssl-dev clang

# 编译nginx 重点是添加 nginx-acme 模块
./configure \
    --prefix=/app/nginx \
    --with-compat \
    --with-file-aio \
    --with-threads \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_mp4_module \
    --with-http_random_index_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-http_v3_module \
    --with-stream \
    --with-stream_realip_module \
    --with-stream_ssl_module \
    --with-stream_ssl_preread_module \
    --add-dynamic-module=/home/wait/tmp/nginx-acme

make clean

make -j 4

# 生成模块
make modules

# so 动态库文件
~/tmp/nginx-1.29.2/objs/ngx_http_acme_module.so
# 直接使用同版本的官方镜像
FROM nginx:1.29.2

# 复制编译好的模块
COPY ./ngx_http_acme_module.so /usr/lib/nginx/modules/

# 暴露端口
EXPOSE 80 443

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

构建容器(非必须)

docker build -t chenwx/nginx_acme:1.29.2 -f Dockerfile .

nginx相关配置

附加了一些 http3 的内容, 非必须;


# 注意 - 加载模块必须放在所有内容的最前面
load_module modules/ngx_http_acme_module.so;

http {
    resolver 8.8.8.8 1.1.1.1;

    # 可选指令 acme_shared_zone, 用于存储所有配置的证书颁发者的证书, 私钥和挑战数据;
    # 该区域默认大小为 256K, 可根据需要增加
    acme_shared_zone zone=ngx_acme_shared:1M;

    # 定义一个名为 letsencrypt_prod 的 ACME 颁发机构实例
    acme_issuer letsencrypt {
        # 指定 ACME 服务提供商的目录 URL, 这里是 Let's Encrypt 的生产环境
        uri         https://acme-v02.api.letsencrypt.org/directory;

        # 个人邮箱 - 用于接收 CA 的重要通知(如证书即将过期等消息)
        contact     mailto:chenwx716@163.com;

        # 同意服务条款, 对于 Let's Encrypt 等 CA 这是必需的步骤
        accept_terms_of_service;

        # 指定状态文件的存储路径, 用于保存 ACME 账户密钥, 非常重要
        state_path  /cert/acme/letsencrypt;
    }
    #===================================================================

    # 配置 HTTP-01 挑战的响应端点
    server {
        listen 80 default_server;

        # 使用一个无效主机名来匹配所有未被其他 server 块精确匹配的域名
        server_name _;

        # ACME 模块会自动处理 /.well-known/acme-challenge/ 的请求, 不需要显式定义
        # 此 location 用于处理所有其他请求
        location / {
            return 301 https://$host$request_uri;
        }
    }

    #===================================================================
    server {
        listen 443 quic reuseport;
        listen [::]:443 quic reuseport;
        http3 on;

        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;

        server_name chenwx.top www.chenwx.top blog.chenwx.top;

        # 声明此 server 块启用 ACME, 并指定使用上面定义的 letsencrypt_prod 颁发机构
        acme_certificate    letsencrypt;

        # 使用动态变量加载由 ACME 模块在内存中管理的证书和私钥
        ssl_certificate     $acme_certificate;
        ssl_certificate_key $acme_certificate_key;

        # ssl 会话缓存
        ssl_certificate_cache max=2;

        ssl_protocols TLSv1.3;
        ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;

        # 优先服务器端加密算法
        ssl_prefer_server_ciphers on;

        # 告知客户端支持 HTTP/3
        add_header Alt-Svc 'h3=":443"; ma=600';

        # sts
        add_header Strict-Transport-Security "max-age=63072000" always;

        location / {
            proxy_pass x.x.x.x;

        }

    }

}

mkdir -p /cert/acme/letsencrypt

然后启动nginx服务即可获取到颁发的证书

最后更新于