logo NodeSeekbeta

[实用向、证书自动申请/自动续期]Nginx原生ACME协议(模块)+案例

开篇借用NGINX Community Blog译文的部分内容。
原文:https://blog.nginx.org/blog/native-support-for-acme-protocol

我们非常高兴地宣布 NGINX 中 ACME 支持的预览版发布。该实现引入了一个新模块 ngx_http_acme_module,提供内置指令,用于直接从 NGINX 配置请求、安装和续证证书。ACME 支持利用了我们的 NGINX-Rust SDK ,作为基于 Rust 的动态模块 ,面向 NGINX 开源用户以及使用 NGINX Plus 的企业 NGINX One 客户。

NGINX 原生支持 ACME 带来了多种优势,简化并提升了整体 SSL/TLS 证书管理流程。能够直接使用 NGINX 指令配置 ACME, 大大减少了人工错误,并消除了传统上管理 SSL/TLS 证书时的大量持续开销。它还减少了对 Certbot 等外部工具的依赖,打造更安全、更简化的工作流程,漏洞更少,攻击面更小。此外,与现有外部工具容易受平台特定限制不同,原生实现确保了更高的可移植性和平台独立性,使其成为现代不断发展的网络基础设施中多功能且可靠的解决方案。

NGINX ACME 工作流程可分为四个步骤:
1、ACME 服务器的设置;
2、共享内存的分配;
3、配置挑战;
4、证书颁发与续期。


说人话就是:加入ACME模块,证书的事(申请/续期啥的)就不管了(反正我是这样,复杂服务可能需要额外调整)。

自己使用已有4个月左右,参考官方以及各种大佬文档,以下是个简单例子,可部分食用,不足之处还望各位指点。

系统Ubuntu20.04

安装基础编译工具和 NGINX 依赖
sudo apt update

sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev pkg-config

libclang-dev git -y

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

source $HOME/.cargo/env

创建文件夹并打开
mkdir -pv /app/nginx/{logs,conf,cache, acme} /app/nginx-build

cd /app/nginx-build

克隆 ACME 模块的源码
git clone https://github.com/nginx/nginx-acme.git /app/nginx-build/nginx-acme
或
git clone [email protected]:nginx/nginx-acme.git /app/nginx-build/nginx-acme

下载 NGINX 源码(也可替换为需要的版本,没记错至少1.25以上)
wget https://nginx.org/download/nginx-1.28.0.tar.gz
解压
tar -zxf nginx-1.28.0.tar.gz

打开文件夹
cd nginx-1.28.0

运行配置参数
./configure
--prefix=/app/nginx
--error-log-path=/app/nginx/error.log
--http-log-path=/app/nginx/access.log
--pid-path=/app/nginx/nginx.pid
--lock-path=/app/nginx/nginx.lock
--http-client-body-temp-path=/app/nginx/cache/client_temp
--http-proxy-temp-path=/app/nginx/cache/proxy_temp
--http-fastcgi-temp-path=/app/nginx/cache/fastcgi_temp
--http-uwsgi-temp-path=/app/nginx/cache/uwsgi_temp
--http-scgi-temp-path=/app/nginx/cache/scgi_temp
--user=nginx
--group=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-mail
--with-mail_ssl_module
--with-stream
--with-stream_realip_module
--with-stream_ssl_module
--with-stream_ssl_preread_module
--with-cc-opt='-g -O2 -ffile-prefix-map=/home/builder/debuild/nginx-1.28.0/debian/debuild-base/nginx-1.28.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC'
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
--add-dynamic-module=/app/nginx-build/nginx-acme

运行配置脚本
make && make modules && make install

打开/app/nginx/conf/nginx.conf,(配置cloudreve网盘服务,路径分流V2RAY)代码如下:

user nginx;
error_log error.log debug;
pid nginx.pid;

load_module modules/ngx_http_acme_module.so;

events {
worker_connections 1024;
multi_accept on;}

http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$host" "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log access.log main;
sendfile on;
tcp_nopush on;
charset utf-8;
keepalive_timeout 65;
gzip on;

resolver 8.8.8.8 1.1.1.1;
acme_issuer letsencrypt {
uri https://acme-v02.api.letsencrypt.org/directory;
contact [email protected];
state_path acme/letsencrypt;
accept_terms_of_service;
}
acme_shared_zone zone=acme_shared:1M;

server {
listen 443 ssl;
server_name xxx.xxx.xyz;#你的域名

acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2; # required ngx 1.27.4+
#---------------------------------------------------------------------------------------------------#
#网盘服务部分
location / {
proxy_pass http://127.0.0.1:5212;#网盘服务端口
proxy_ssl_server_name on;
proxy_redirect off;
sub_filter_once off;
sub_filter "xxx.xxx.xyz" $server_name;#你的域名
proxy_set_header Host "xxx.xxx.xyz";#你的域名
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language "zh-CN";}
#---------------------------------------------------------------------------------------------------#
#V2RAY服务部分
location /你的路径 { #路径,和v2ray的配置保持一致
proxy_redirect off;
proxy_pass http://127.0.0.1:9999; #端口,和V2RAY的配置保持一致
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
#---------------------------------------------------------------------------------------------------#
}

server {
listen 80 default_server;
server_name _;
location / {
return 301 https://$host$request_uri;}
}
}

进入文件夹
cd /app/nginx/
验证配置文件语法
./sbin/nginx -c conf/nginx.conf -t

大概率会报错
报错nginx: [emerg] mkdir(),则创建对应文件夹
mkdir -p 路径/文件夹

报错nginx: [emerg] getpwnam("nginx") failed,则运行
useradd -r nginx

每处理一条报错,都执行验证配置文件语法命令和处理报错,直到不再报错
./sbin/nginx -c conf/nginx.conf -t

启动NGINX
./sbin/nginx -c conf/nginx.conf

设置NGINX自启,进入/etc/systemd/system文件夹,创建nginx.service文件
cd /etc/systemd/system/

touch nginx.service

复制如下代码:
[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.target

[Service]
Type=forking
#PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/app/nginx/sbin/nginx -t -c /app/nginx/conf/nginx.conf
ExecStart=/app/nginx/sbin/nginx
ExecReload=/app/nginx/sbin/nginx -s reload
ExecStop=/app/nginx/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=default.target

重新加载守护进程
systemctl daemon-reload
设置自启
systemctl enable nginx

到这里,nginx部分就完成了。


网盘搭建(根据自己需求配置,此处为简单例子)
打开目录
cd /usr/bin

安装网盘(注意AMD、ARM,还有想要的版本号)
wget https://github.com/cloudreve/Cloudreve/releases/download/3.8.3/cloudreve_3.8.3_linux_amd64.tar.gz

解压
tar -zxvf cloudreve_3.8.3_linux_amd64.tar.gz

赋予执行权限
chmod +x ./cloudreve

启动 Cloudreve
./cloudreve

浏览器访问http://服务器IP:5212,使用首次启动Cloudreve打印出来的账号密码登录,建议先干这些事:
1、修改密码
2、修改用户名
3、注册管理
4、管理用户组各种权限

设置好之后,Ctrl+C结束Cloudreve

设置Cloudreve自启,进入/etc/systemd/system/文件夹,创建cloudreve.service文件,写入
[Unit]
Description=Cloudreve
Documentation=https://docs.cloudreve.org
After=network.target
After=mysqld.service
Wants=network.target

[Service]
WorkingDirectory=/usr/bin
ExecStart=/usr/bin/cloudreve
Restart=on-abnormal
RestartSec=5s
KillMode=mixed

StandardOutput=null
StandardError=syslog

[Install]
WantedBy=multi-user.target

重新加载配置
systemctl daemon-reload
设置cloudreve自启
systemctl enable cloudreve

启动/重启nginx和cloudreve服务(或者直接reboot),证书就自动申请好了,并且到期自动续期,不会出现证书到期时出现的各种问题(之前ACME自动申请和管理证书,nginx需要reload啥的),v2ray部分不再展开。

12
  • 支持!好奇哪里要用到 rust

  • 谢谢分享

  • 可惜目前主要支持 HTTP-01 验证,DNS 验证的支持还不够完善~

  • 我记得有自动化工具 或者caady

  • @Bene #1 听取某位大佬指导:与许多 NGINX 模块一样,ngx_http_acme_module 是一个动态模块,由于该模块是基于 Rust 开发的,您的编译环境除了需要常规的 C 编译器和 NGINX 依赖库外,还必须安装 Rust 工具链。

  • @Mofeng #4 之前我用自动化工具,证书到期,某些服务会出现问题,需要重启或者reload nginx,后来才开始用这个就没管过证书的事了 xhj007

  • @yannis #3 看来是位隐藏大佬,我的小鸡之前证书到期会有问题,所以转用这个,用了之后就没毛病了,其他深奥也不太懂 ac01

  • 一直在关注这个项目 明年才会有dns 还是先用acme

    acme本身也支持reload命令
    --reloadcmd "nginx -s reload 2>/dev/null || true"

  • 这还要自己编译,nginx升级不兼容之类的不麻烦死了

12

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72787位seeker

🎉欢迎新用户🎉