Nginx Proxy Manager 作为一个可视化反向代理工具,没有直接提供使用文件路径配置ssl证书的方法,都是用网页控制台来上传ssl证书内容,或者直接自动化申请证书。本文提供了python脚本,使用官方的API完成证书内容更新。API文档:https://documenter.getpostman.com/view/4475423/2s93mBvyLZ#31755761-c816-4820-9f0a-80cda5b983c6

我也想直接用Nginx Proxy Manager提供的自动申请证书功能,但是本地docker部署之后一直没有弄成功,只能退而求其次用其他工具自动申请证书,例如1panel,certd等,这两个我都有在用。本文是使用1panle自动下载证书。

安装Nginx Proxy Manager

这个就不多做介绍,在1panle中直接点击安装就行。

添加证书

在使用脚本之前,还需要自己手动添加一次证书,使用下面的Upload cert的API,如果不先自行创建,那么应该就需要用Create Certificate这个API,使用复杂一些。

进入Nginx Proxy Manager后台:

添加证书,随便起一个名字,这个之后会用到。

使用脚本更新

#!/usr/bin/env python3
import requests
import sys

# === 从环境变量读取配置 ===
NPM_HOST = "http://localhost:30081"   #这里是面板地址
USERNAME = "sirius_shiyu@qq.com"  # Nginx Proxy Manager账号,一般为邮箱
PASSWORD = " " # 密码
CERT_NAME = "songshiyu.cn" #之前设置的
CERT_PATH = "/home/xxx/docker/ssl/fullchain.pem" #证书,根据自己的证书名字设置
KEY_PATH = "/home/xxx/docker/ssl/privkey.pem" #私钥路径


# === 登录获取 JWT Token ===
session = requests.Session()
resp = session.post(f"{NPM_HOST}/api/tokens", json={
    "identity": USERNAME,
    "secret": PASSWORD
})
resp.raise_for_status()
token = resp.json()["token"]

headers = {
    "Authorization": f"Bearer {token}"
}

# === 获取所有证书 ===
certs = session.get(f"{NPM_HOST}/api/nginx/certificates", headers=headers).json()

# 打印所有证书的名称,如果找不到对应的证书就打印出来检查
#print("现有证书列表:")
#for cert in certs:
#    print(cert)

# 查找目标证书
target_cert = next((c for c in certs if c["nice_name"] == CERT_NAME), None)

if not target_cert:
    print(f"找不到名称为 '{CERT_NAME}' 的证书")
    sys.exit(1)

cert_id = target_cert["id"]

# === 更新证书内容 ===
# === 上传证书 ===
upload_url = f"{NPM_HOST}/api/nginx/certificates/{cert_id}/upload"

# Open the certificate and key files
with open(CERT_PATH, "rb") as cert_file, open(KEY_PATH, "rb") as key_file:
    files = {
        "certificate": cert_file,
        "certificate_key": key_file
    }

    # Perform the POST request to upload the certificate and key
    upload_resp = session.post(upload_url, headers=headers, files=files)
    upload_resp.raise_for_status()  # If there's an error, raise an exception

print(f"成功上传证书 '{CERT_NAME}'")

这个打印信息是为了方便调试的,将现有的证书打印出来,可以选择对应的证书进行更新,更新最重要的是证书对应的id。

配合1panle 自动申请证书

1panel自动化申请完证书之后可以自动执行脚本,每次申请完后自动运行一遍这个python脚本就行了。