# OpenResty Gateway 这个目录用于通过 Docker Compose 启动 OpenResty 网关,并使用 Certbot 申请和续期 Let's Encrypt 证书。 ## 前置条件 - Linux 服务器 - Docker 和 Docker Compose - `openssl` - `crontab`,可选,用于安装自动续期任务 - 域名 DNS 已解析到当前服务器 当前配置使用 `network_mode: host`,OpenResty 会直接监听宿主机端口。 ## 脚本结构 - `init-certs.sh`:首次初始化入口,内部调用 `scripts/init-certs-core.sh`。 - `add-domain-certs.sh`:在 OpenResty 已运行时追加新域名证书,内部调用 `scripts/add-domain-certs-core.sh`。 - `reload.sh`:修改 nginx 配置后校验并重载 OpenResty。 - `uninstall.sh`:卸载入口,目前用于卸载证书自动续期 cron。 - `scripts/`:放具体实现脚本,包括 nginx 域名模板生成、证书初始化核心逻辑、手动续期、安装和卸载续期 cron。 ## 首次部署 进入目录: ```bash cd /path/to/openresty-gateway ``` 如果需要直接执行脚本,可以先添加执行权限: ```bash chmod +x *.sh scripts/*.sh ``` 首次申请证书并启动服务: 先确认 `init-certs.sh` 里的 `DOMAINS` 和 `CERT_EMAIL` 已经按当前部署环境配置好。 ```bash sh init-certs.sh ``` 默认情况下,脚本只校验 nginx 配置是否存在,不会自动创建新站点配置。缺配置时可以显式生成基础模板: ```bash sh init-certs.sh --create-missing-conf ``` 这个脚本会: 1. 校验每个域名都有 nginx 配置、配置里放行 `/.well-known/acme-challenge/`,且 nginx 引用的证书域名都已加入 `DOMAINS`。 2. 为缺失的证书路径生成临时 dummy 证书。 3. 启动 OpenResty,保证 `/.well-known/acme-challenge/` 可以访问。 4. 删除本次创建的 dummy 证书文件。 5. 运行 Certbot 分别为每个域名申请正式证书。 6. 重启 OpenResty 让正式证书生效。 7. 如果系统有 `crontab`,安装证书自动续期 cron 任务。 不想在初始化时安装自动续期任务: ```bash sh init-certs.sh --skip-renew-cron ``` 重复执行 `init-certs.sh` 不会强制重签已有证书;Certbot 会保留还没到期的证书。 重复执行时也不会重复添加 cron;安装脚本会先删除旧任务块,再写入新任务。 ## 追加域名证书 当 OpenResty 已经在线运行,只需要给新域名补证书时,使用 `add-domain-certs.sh`。 先把要新增的域名写入 `add-domain-certs.sh` 的 `DOMAINS`,这里只放本次要新增的域名: ```sh DOMAINS=" proxy.sggai.site gitea.sggai.site " ``` 然后执行: ```bash sh add-domain-certs.sh ``` 这个脚本会: 1. 校验 Docker Compose 配置,并确认 `openresty` 容器已经在运行。 2. 检查每个新增域名是否已有 nginx 配置。 3. 如果缺少 `conf/conf.d/.conf`,自动调用 `scripts/ensure-domain-conf.sh` 生成基础模板。 4. 为缺失证书的新域名生成临时 dummy 证书。 5. 校验并重载 OpenResty,让新增配置和 dummy 证书生效。 6. 检查本机和公网 HTTP-01 challenge 路径是否可访问。 7. 删除本次创建的 dummy 证书,调用 Certbot 申请正式证书。 8. 再次重载 OpenResty,让正式证书生效。 如果服务器无法从本机访问自己的公网域名,但外部访问是正常的,可以跳过公网探测: ```bash sh add-domain-certs.sh --skip-public-http-check ``` 自动生成的 nginx 配置是静态站点基础模板,只保证证书申请和 HTTPS 站点能启动。如果新域名需要反向代理到后端服务,请按业务需要修改 `conf/conf.d/.conf`,再执行: ```bash sh reload.sh ``` ## 日常启动和停止 启动: ```bash docker compose up -d openresty ``` 停止: ```bash docker compose down ``` 重启: ```bash docker compose restart openresty ``` 检查配置: ```bash docker compose config docker compose exec openresty openresty -t ``` 查看日志: ```bash docker compose logs -f openresty ``` ## 证书续期 手动续期: ```bash sh scripts/renew-certs.sh ``` `scripts/renew-certs.sh` 使用 `certbot renew`,Certbot 会自己判断证书是否快过期;没到续期时间不会真正重签。 ## 安装自动续期 安装每天 03:00 自动续期: ```bash sh scripts/install-renew-cron.sh ``` 安装脚本可以重复执行。它会先删除旧的自动续期任务块,再写入新的任务,避免重复添加。 自定义执行时间,例如每天 04:30: ```bash SCHEDULE="30 4 * * *" sh scripts/install-renew-cron.sh ``` 查看当前 crontab: ```bash crontab -l ``` 卸载自动续期: ```bash sh uninstall.sh ``` 自动续期日志: ```bash tail -f logs/cert-renew.log ``` ## AI 网关 mock 规则 `conf/conf.d/000-ai.sggai.site-mock-small-chat.conf` 会优先于 `ai.sggai.site.conf` 加载。 它会拦截: - 路径:`/v1/chat/completions` - 方法:`POST` - JSON 中 `"stream": false` - 请求体不超过 `1024` 字节 - `messages` 文本内容总长度不超过 `20` 字节 命中后直接返回 mock 响应: ```json { "id": "chatcmpl-mock", "object": "chat.completion", "created": 1716030000, "model": "xxx", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "ok" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2 } } ``` 不满足 mock 条件的请求会继续转发到: ```text http://10.1.0.1:3001 ``` ## 注意事项 - `certs/`、`logs/`、运行时 webroot 文件默认不提交到 Git。 - `conf/conf.d/00-default-deny.conf` 是默认拒绝站点,用于丢弃没有匹配到具体 `server_name` 的 HTTP 请求,并拒绝未知 SNI 的 HTTPS 握手。 - 如果证书文件不存在,OpenResty 的 HTTPS 配置会启动失败;首次部署请先运行 `init-certs.sh`。 - `ai.sggai.site` 当前通过 `000-` 前缀配置文件覆盖原配置,`openresty -t` 可能出现同名 server 被忽略的 warning。 - 如果需要透传带下划线的请求头,例如 `Session_id`,需要确认 Nginx 的 `underscores_in_headers` 策略是否符合预期。