English · 部署说明(Docker) · Docker Hub
https_ssl 是一个基于 Flask 和 OpenSSL 开发的自签证书管理系统,旨在简化 SSL 证书的创建、管理和验证过程。系统提供了直观的 Web 界面,使用户能够轻松创建自签名 CA 证书、签发服务器证书,并配置反向代理服务,无需深入了解复杂的 OpenSSL 命令。
本仓库在上游项目基础上完成 Linux / Docker 适配:反向代理不再依赖 Windows 专用的 proxy.exe,改为同一容器内的 nginx 进程实现,可在飞牛 NAS 等 Linux 环境下完整使用全部功能。
- 创建自定义虚拟证书颁发机构(CA)
- 支持设置 CA 私钥密码保护
- 查看和下载 CA 证书
- 管理 CA 证书生命周期
- 基于创建的 CA 签发服务器证书
- 支持多域名和多 IP 地址的 SAN 扩展
- 证书批量管理和删除
- 证书和私钥的安全下载
证书名称只能包含中英文、数字、下划线、连字符和点,长度 1–64,且不能重名
(重名会返回 409,请先删除旧证书)。ca为保留名称。
- 验证已签发证书的有效性:解析证书、校验私钥配对、检查有效期,
再与证书的 SAN 比对所填地址,最后在回环地址完成一次真实 TLS 握手 - 支持上传自定义证书进行验证(此时按系统信任库校验证书链)
- 基于已签发证书配置 HTTPS 反向代理
- 将 HTTP 服务转换为 HTTPS 服务
- 访问时忘记写
https://也会自动跳到 HTTPS(不会停在 400) - 支持多服务、多站点配置,配置变更热加载
- 管理反向代理服务的启动和停止
整个系统只运行一个容器,Flask 与 nginx 在同一容器内由 entrypoint.sh 一并拉起:
┌───────────────────────────────────────────┐
│ qilin_ssl │
│ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ nginx 进程 │ │ Flask 进程 │ │
│ │ · TLS 终止 │◄───│ · 证书签发 │ │
│ │ · 多站点路由 │ │ · CA 管理 │ │
│ │ · 热加载配置 │ │ · 反代配置管理 │ │
│ └──────────────┘ └──────────────────┘ │
│ :14000 等 :2002 │
└───────────────────────────────────────────┘
- nginx:在容器内承担 TLS 终止与请求转发,站点配置位于
/app/proxy/sites。 - Flask:证书全生命周期管理面板,同时负责生成 nginx 站点配置并执行
nginx -s reload热加载。
反代不再依赖任何 Windows 专用二进制,也无需挂载 Docker socket,容器权限更小。
完整的 Docker 部署步骤、配置说明、升级与排错见 部署说明(Docker)。
- Linux(已在飞牛 NAS / fnOS、Debian 12 验证)
- Docker Engine 20.10+ 与 Docker Compose v2
- 宿主机无需安装 Python / OpenSSL / nginx,它们都在镜像内
镜像已发布到 Docker Hub:
nameguoguo/https_ssl(同时支持 amd64 / arm64), 可以不克隆代码直接拉取运行。使用 host 网络模式,且只支持 host,需要 Linux。macOS / Windows 的 Docker Desktop 没有 host 模式,请在 Linux 虚拟机里跑;桥接模式已在 1.6.2 移除 (见下方「端口怎么放行」)。
方式一:一键脚本(推荐)
curl -fsSL https://raw.githubusercontent.com/guoxpeng/https_ssl/main/install.sh | bash脚本会拉取 Docker Hub 上的镜像并启动,不需要 git、不编译,几十秒装完。
方式二:直接用 Docker Hub 镜像
mkdir https_ssl && cd https_ssl
curl -fsSL -o docker-compose.yml \
https://raw.githubusercontent.com/guoxpeng/https_ssl/main/docker-compose.yml
docker compose up -d国内直连 Docker Hub 经常超时,可以在 .env 里写 QILIN_IMAGE=<加速站>/nameguoguo/https_ssl:latest
换用镜像加速站,或改用方式三从源码构建。
方式三:从源码构建
git clone https://github.com/guoxpeng/https_ssl.git
cd https_ssl
docker compose -f docker-compose.build.yml up -d --build然后浏览器访问 http://<服务器IP>:2002,用下面的账号登录:
- 用户名:
admin - 密码:
admin
密码在首次启动时用于初始化账号,之后以哈希形式存于用户表(见 QILIN_USERS_FILE),
请及时在「设置」页修改。想换成别的初始密码,见下方环境变量表。
升级到新版本:
docker compose pull && docker compose up -d。 用户表默认落在挂载出来的./data/users.json,升级不会丢密码。
它在做什么:把别的设备上的 HTTP 服务,用本机(跑面板的这台机器)的端口 代理成 HTTPS 服务。浏览器访问的是本机地址,TLS 在本机终止,后端服务在哪台机器上都不影响。
两个地址怎么填:
| 字段 | 填什么 |
|---|---|
| 原本地址 | 后端服务的真实地址,可以是别的设备,如 http://192.168.5.5:5244 |
| 反代后地址 | IP 只能填本机(跑面板的这台机器),如 https://192.168.5.3:5245 |
原因:HTTPS 是在本机终止的,浏览器敲的也是本机地址,所以证书的 SAN 里必须有本机 IP, 访问时也只能用本机 IP。
后端自己就是 HTTPS? 不用让面板再签一张——「证书类型」选上传自定义证书, 把后端服务自己的证书和私钥传上来即可,原本地址照旧填后端的原 IP 和端口。
端口怎么放行:host 网络模式,面板里填端口 → 点启用 → 结束,能访问了,
不用改 docker-compose.yml,也不用重建容器。
为什么不做 bridge 模式(1.6.2 起已移除):Docker 桥接网络的端口映射在 容器创建那一刻就写死了,事后加不进去。所以在 bridge 下,面板里填的端口容器内 nginx 会正常监听,外面却连不上 —— 看起来就像「没生效」,排查成本很高。
如果你现在正好卡在这里:
ss -ltn | grep -E ':(5245|14000)' # 宿主机有没有在监听 sudo docker inspect -f '{{.HostConfig.NetworkMode}}' qilin_ssl # 期望 host第二条输出
bridge的话,用图形界面把容器网络模式改成 host 重建即可, 数据卷保留就不会丢证书和反代配置。
两种模式的完整对比见 部署说明(Docker)→ 网络模式。
面板里「创建」与「启用」分开,只做一步都不会监听端口:
- 点「新增」填完信息保存 —— 服务记录建好了,但状态是未启用,端口还没开始监听;
- 在列表里把开关打开 —— 这一步才真正生成 nginx 站点并
nginx -s reload。
挑一个宿主机上没被占用的端口。万一撞车,只有这一个站点加载失败
(nginx -t 会先拦下来,其他已启用服务不受影响),但你这个入口会打不开。先查一下:
ss -lntp | grep <端口> # 有输出就是被占了- 登录系统后,在主页点击「创建」按钮
- 填写机构名称(可选)
- 设置私钥密码(可选,增强安全性)
- 点击「创建」完成 CA 证书生成
- 下载 CA 证书并安装到本地受信任的根证书颁发机构
- 在主页的「证书列表」区域点击「新增」按钮
- 填写证书名称
- 输入需要支持的 IP 地址(多个地址用分号分隔)
- 输入需要支持的域名(多个域名用分号分隔)
- 点击「创建」完成证书申请
- 下载证书和私钥文件
- 点击侧边栏的「反向代理」菜单
- 点击「新增」按钮
- 填写服务名称(该名称同时作为证书名与站点配置名)
- 输入原始服务地址(如
http://192.168.5.3:4000) - 输入反向代理后的地址(如
https://192.168.5.3:14000) - 选择证书类型(https_ssl 申请的证书或上传自定义证书)
- 点击「创建」完成配置
- 点击开关启用服务
配置变更会通过 nginx -s reload 热加载,不影响其他已启用服务。
浏览器把「192.168.5.3:14000」补全成 http://192.168.5.3:14000 时,明文请求会打到
TLS 端口上。nginx 默认对这种情况回 400「The plain HTTP request was sent to HTTPS
port」,看着像服务坏了。
面板生成的每个 HTTPS 站点都带一条
error_page 497 =301 https://$host:$server_port$request_uri;把这种请求 301 跳到 HTTPS,路径与查询参数原样保留 ——
http://192.168.5.3:14000/login?next=%2F 会跳到 https://192.168.5.3:14000/login?next=%2F。
所以直接输入 192.168.5.3:14000 就能进,不必手打协议头。
只对本面板管理的 HTTPS 站点生效。fnOS 自带的管理界面(443 / 5667)由 fnOS 的 nginx 提供,不受这里影响。
- 点击侧边栏的「证书验证」菜单
- 输入需要验证的 IP 地址或域名
- 选择证书类型(https_ssl 申请的证书或上传自定义证书)
- 点击「验证」按钮查看验证结果
支持以下环境变量:
| 变量 | 默认值 | 说明 |
|---|---|---|
QILIN_ADMIN_PASSWORD |
admin |
首次启动创建 admin 账号用的初始密码。只在还没有 users.json 时生效,之后改这个变量不会影响已有账号 |
QILIN_SECRET_KEY |
随机 | 会话签名密钥。留空时每次启动随机生成,容器重启会导致所有登录失效,建议固定 |
QILIN_COOKIE_SECURE |
0 |
置 1 时会话 Cookie 仅在 HTTPS 下发送(面板经 HTTPS 反代暴露时使用) |
QILIN_PORT |
2002 |
面板监听端口。host 网络模式下 Flask 直接绑宿主机这个端口 |
QILIN_USERS_FILE |
/app/users.json |
用户表位置。默认在容器内,重建容器会丢;compose 部署时指向挂载出来的 /app/data/users.json |
TZ |
UTC |
容器时区。证书有效期等时间戳按它显示,国内建议 Asia/Shanghai |
QILIN_PROXY_DIR |
/app/proxy |
反向代理站点配置与证书目录 |
QILIN_PROXY_LISTEN_HOST |
空 | 代理监听地址,留空表示监听全部地址 |
QILIN_OPENSSL |
/usr/bin/openssl |
OpenSSL 可执行文件路径 |
scripts/smoke_test.py 会在临时目录里完整跑一遍流程(建 CA → 签发 → 验证 →
反代创建/启停/删除 → 删除联动),不会读写项目里的真实数据:
python scripts/smoke_test.py
# Windows 下若 openssl 不在 PATH:
# set QILIN_OPENSSL=C:\Program Files\Git\usr\bin\openssl.exe容器内的真机验证脚本(针对已运行的面板):
docker exec -e QILIN_PASS='你的密码' qilin_ssl bash /app/_verify_e2e.sh
docker exec -e QILIN_PASS='你的密码' qilin_ssl bash /app/_verify_proxy.sh- 系统生成的 CA 证书和私钥仅用于测试和开发环境
- 在生产环境中,建议使用正规 CA 机构签发的证书
- 请妥善保管 CA 私钥,避免泄露
- CA 私钥不会通过面板分发(
/download/ca/只放行根证书https-ssl-ca.crt),
需要备份请直接从宿主目录./data/ca取 - 定期更换用户密码,提高系统安全性
- 容器内 nginx 与 Flask 以同一用户运行,请勿将该容器暴露到不可信网络
- 管理员默认账号为
admin/admin,首次启动时由QILIN_ADMIN_PASSWORD初始化
(缺省admin,启动日志会提示改密码);请尽快在「设置」页更换
- 证书不被浏览器信任怎么办?
- 需要将生成的 CA 证书安装到操作系统的受信任根证书存储区
- 装完把浏览器完全退出再打开:Edge / Chrome 会把“继续访问”的证书例外保留到
会话结束,装 CA 之前就开着的浏览器会一直显示不安全,重启才清掉 ——
新开一个 InPrivate / 无痕窗口就能 5 秒自测。必要时用新配置验一下:
msedge.exe --headless=new --user-data-dir=%TEMP%\edgecerttest --dump-dom https://<IP>:<端口>/
- 如何在移动设备上信任证书?
- 将 CA 证书发送到移动设备并在设备设置中安装证书
- iOS 还要在「设置 → 通用 → 关于本机 → 证书信任设置」里手动启用完全信任
- https 显示「不安全」但服务能用?
- 先看访问的是哪个地址:
http://<IP>:2002是面板本身,它就是明文 HTTP, 永远标不安全(想绿锁就用反代给面板自己也套一层 HTTPS) - 再看地址在不在证书的 SAN 里(换 IP / 换域名访问就是名称不匹配), 面板「证书验证」页可以填地址自检
- 点地址栏的锁看具体原因:显示「部分内容不安全」是后端页面里有
http://资源(混合内容),属于后端应用的问题 - 详细排查步骤见 INSTALL.md 的「浏览器还是显示「不安全」?」
- 先看访问的是哪个地址:
- 反向代理服务无法启动?
- 确认所填服务名对应的证书已存在(证书名需与服务名一致)
- 检查容器内 nginx 配置是否正确:
docker exec qilin_ssl nginx -t - 检查宿主端口是否被别的服务占用:
ss -lntp | grep <端口> - 确认容器跑在 host 网络模式(本项目只支持 host):
docker inspect -f '{{.HostConfig.NetworkMode}}' qilin_ssl
- 修改反向代理端口后不生效?
- 面板保存配置后会自动重载 nginx。若未生效,手动执行:
docker exec qilin_ssl nginx -s reload
- 面板保存配置后会自动重载 nginx。若未生效,手动执行:
- 创建反向代理后列表里没有 / 提示启动失败?
- 「创建」之后还要点开关启用才会真正监听端口,只保存不启用是不生效的
- 确认容器网络模式是 host(
docker inspect -f '{{.HostConfig.NetworkMode}}' qilin_ssl), bridge 下容器内监听成功但宿主访问不到 - 服务启动失败时面板会直接显示 nginx 的报错原文,按提示处理即可
- 证书验证提示"证书未覆盖地址"?
- 说明所填 IP/域名不在该证书的 SAN 列表中。请核对申请证书时填写的
IP 与域名(支持*.example.com形式的通配)
- 说明所填 IP/域名不在该证书的 SAN 列表中。请核对申请证书时填写的
- 证书验证提示"证书链校验失败"?
- 自定义证书是按系统信任库校验的:自签证书或缺少中间证书的链都会失败,
浏览器同样会报警告。把 CA 证书装进系统信任库,或换用完整链后再试
- 自定义证书是按系统信任库校验的:自签证书或缺少中间证书的链都会失败,
- 重新创建 CA 后原来签发的证书还能用吗?
- 不能。新 CA 无法验证旧证书,面板会自动停用受影响的反向代理服务,
需要重新签发证书后再启用
- 不能。新 CA 无法验证旧证书,面板会自动停用受影响的反向代理服务,
当前版本:v1.7.1
变更记录见 CHANGELOG.md。
本项目采用 MIT 许可证。
血缘关系:作者源库 linzxcw/qilin_SSL(原始项目)
→ guoxpeng/fnos_qilin_SSL(其 fnOS 适配分支)
→ 本仓库 https_ssl(在后者基础上完成 Linux / Docker 适配,反代由 Windows 二进制改为同容器内的 nginx)。
注意:原始仓库未附许可证文件。若计划公开发布,建议先联系原作者取得授权。