feat: add https websocket ingress baseline
This commit is contained in:
@@ -88,7 +88,7 @@ services:
|
||||
ORBIT_CONSOLE_QUEUE_ID: ${ORBIT_CONSOLE_QUEUE_ID:-}
|
||||
ORBIT_METRICS_ADDR: ${ORBIT_METRICS_ADDR:-}
|
||||
ports:
|
||||
- "${ORBIT_HTTP_PORT:-8080}:8080"
|
||||
- "${ORBIT_HTTP_BIND:-127.0.0.1}:${ORBIT_HTTP_PORT:-8080}:8080"
|
||||
stop_grace_period: 30s
|
||||
|
||||
volumes:
|
||||
|
||||
122
deploy/nginx/orbit.conf.example
Normal file
122
deploy/nginx/orbit.conf.example
Normal file
@@ -0,0 +1,122 @@
|
||||
# Orbit HTTPS/WSS 入口示例。
|
||||
# 将 orbit.example.com 和证书路径替换成正式值后,放到 Nginx 的 conf.d 目录。
|
||||
# 本文件位于 http 配置上下文中;map/limit_req_zone 不能放进 server 块。
|
||||
|
||||
map $http_upgrade $orbit_connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
limit_req_zone $binary_remote_addr zone=orbit_console_login:10m rate=10r/m;
|
||||
|
||||
upstream orbit_backend {
|
||||
server 127.0.0.1:8080;
|
||||
keepalive 64;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name orbit.example.com;
|
||||
|
||||
# ACME HTTP-01 或其他证书签发工具可使用此目录。
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/orbit-acme;
|
||||
default_type text/plain;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 308 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
http2 on;
|
||||
server_name orbit.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/orbit.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/orbit.example.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_session_cache shared:orbit_tls:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_tickets off;
|
||||
|
||||
client_max_body_size 1m;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_send_timeout 60s;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
|
||||
# 长连接只用于 Worker 和结果订阅;心跳由协议负责,代理不能自行关闭空闲会话。
|
||||
location = /v1/worker/connect {
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $orbit_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;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 1h;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location = /v1/events/connect {
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $orbit_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;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 1h;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
# 控制台登录额外限制来源 IP 的尝试速率;业务任务速率仍由 Orbit 的持久化配额和授权决定。
|
||||
location = /console/auth/login {
|
||||
limit_req zone=orbit_console_login burst=5 nodelay;
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
|
||||
location = /health/live {
|
||||
access_log off;
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 5s;
|
||||
}
|
||||
|
||||
location = /health/ready {
|
||||
access_log off;
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 5s;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://orbit_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,8 @@
|
||||
|
||||
新增 `deploy/docker-compose.yml` 作为单节点可部署基线:MySQL 健康检查通过后依次执行迁移和 `orbit-admin verify`,核验成功才启动 Orbit;`make compose-check` 提供不泄露密码的静态配置门禁,首次管理员初始化和域名/同源访问说明见[Compose 部署基线](22-compose-deployment.md),实际正常启动与失败阻断证据见[Compose 部署基线验证](reports/phase-9-compose-deployment.md)。该基线不替代生产数据库高可用、正式 Secret、容量、备份和 RPO/RTO 验收。
|
||||
|
||||
新增 `deploy/nginx/orbit.conf.example` 作为可选 HTTPS/WSS 入口模板:Compose 默认只将业务端口绑定到 `127.0.0.1`,Nginx 负责 TLS 终止、WebSocket 升级、健康探针代理和控制台登录来源限速;配置语法及端口边界证据见[HTTPS/WSS 入口基线验证](reports/phase-10-ingress.md)。Nginx 是部署入口,不会成为 Orbit 服务端的业务依赖,真实域名、正式证书、入口故障和公网重连仍需目标环境验收。
|
||||
|
||||
## 2. 持续推进方式
|
||||
|
||||
每个阶段按以下顺序推进:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
本文给出单节点部署的可重复入口,适合开发、验收和小规模生产前置环境。它把 MySQL、迁移、schema 核验和 Orbit 服务串成一条有明确失败边界的启动链路;生产多节点、数据库高可用、备份恢复和容量门禁仍按[生产验收](05-production-acceptance.md)执行。
|
||||
|
||||
前置条件:Docker Engine、Docker Compose v2.20 或更高版本;正式环境还应具备镜像仓库、Secret 管理器和 HTTPS 反向代理。
|
||||
前置条件:Docker Engine、Docker Compose v2.20 或更高版本;如果使用仓库里的 Nginx 示例,需要 Nginx 1.25.1 或更高版本;正式环境还应具备镜像仓库、Secret 管理器和 HTTPS 反向代理。
|
||||
|
||||
## 1. 启动契约
|
||||
|
||||
@@ -38,6 +38,7 @@ export ORBIT_DB_NAME=orbit
|
||||
export ORBIT_DB_USER=orbit_runtime
|
||||
export ORBIT_DB_PASSWORD='从秘密管理器读取'
|
||||
export ORBIT_DB_ROOT_PASSWORD='从秘密管理器读取'
|
||||
export ORBIT_HTTP_BIND=127.0.0.1
|
||||
export ORBIT_HTTP_PORT=8080
|
||||
```
|
||||
|
||||
@@ -87,7 +88,9 @@ curl --fail http://127.0.0.1:"${ORBIT_HTTP_PORT:-8080}"/health/ready
|
||||
|
||||
Orbit Console 使用当前页面的同源地址调用服务端,浏览器不需要再填写 API URL,也不需要上传凭据 JSON 才能查看控制台。直接访问 `http://主机:端口/console/`,未登录会跳转到 `/console/login`。
|
||||
|
||||
接入域名时,将 HTTPS 反向代理转发到 Orbit 的 `8080` 端口,并保留 WebSocket Upgrade/Connection 头;浏览器访问的域名就是 Console 自动使用的 API 地址。`ORBIT_HTTP_PORT` 只控制主机映射端口,不是业务域名配置。TLS 证书、域名和安全头由反向代理或入口网关管理。
|
||||
接入域名时,参考 [`deploy/nginx/orbit.conf.example`](../deploy/nginx/orbit.conf.example),将 HTTPS 反向代理转发到 Orbit 的 `8080` 端口,并保留 WebSocket Upgrade/Connection 头;浏览器访问的域名就是 Console 自动使用的 API 地址。`ORBIT_HTTP_BIND` 控制主机监听地址,`ORBIT_HTTP_PORT` 控制主机映射端口;两者都不是业务域名配置。生产建议保持 `ORBIT_HTTP_BIND=127.0.0.1`,只允许同机 Nginx 访问。TLS 证书、域名和安全头由反向代理或入口网关管理。
|
||||
|
||||
修改 Nginx 配置后先执行 `nginx -t`,再平滑加载配置;不要在未验证证书、HTTP 到 HTTPS 跳转和 WSS 升级前切换公网流量。Nginx 不应代理 Orbit 的独立 metrics 监听,metrics 只在内部采集网络开放。
|
||||
|
||||
## 4. 日常操作与失败处理
|
||||
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
| [P7 Console 真实链路回归](reports/phase-7-console-e2e.md) | 真实 MySQL、Worker、流程、结果订阅与控制台读取闭环 |
|
||||
| [首次部署与控制台任务闭环](reports/phase-8-console-e2e.md) | 从空库初始化管理员、Docker 启动、控制台登录、WS Worker、重试和定时任务 |
|
||||
| [Compose 部署基线验证](reports/phase-9-compose-deployment.md) | MySQL、迁移、核验、Orbit 启动顺序及失败门禁 |
|
||||
| [HTTPS/WSS 入口基线验证](reports/phase-10-ingress.md) | 本机端口边界、Nginx TLS、WebSocket 升级和健康探针配置 |
|
||||
| [20 运行与发布手册](20-operations-runbook.md) | 启动、发布、滚动停止、数据库恢复、备份和事故处理 |
|
||||
| [21 容器发布说明](21-container-deployment.md) | 最小镜像、迁移/核验/启动顺序、探针和发布边界 |
|
||||
| [22 Compose 部署基线](22-compose-deployment.md) | MySQL、迁移、核验、Orbit 服务和首次管理员初始化的可重复启动链路 |
|
||||
| [Nginx HTTPS/WSS 入口示例](../deploy/nginx/orbit.conf.example) | 域名、TLS、WebSocket 升级、健康探针和控制台登录限速 |
|
||||
| [09 可靠结果订阅](09-result-subscription-core.md) | 提交水位、冻结结果与可靠交付 |
|
||||
| [10 Weave决策与交付](10-workflow-engine-core.md) | 有限步骤决策和内部结果Inbox |
|
||||
| [11 Weave实例受理](11-workflow-admission.md) | 固定版本、初始图和首批任务事务 |
|
||||
|
||||
40
docs/reports/phase-10-ingress.md
Normal file
40
docs/reports/phase-10-ingress.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# HTTPS/WSS 入口基线验证
|
||||
|
||||
验证日期:2026-09-22
|
||||
验证范围:Orbit 主机端口边界、Nginx HTTPS 配置语法、WebSocket Upgrade 路由、健康探针和控制台登录限速配置。
|
||||
验证环境:Docker Desktop、Nginx 1.27 Alpine、当前 Compose 配置。
|
||||
|
||||
## 已通过
|
||||
|
||||
### Orbit 端口边界
|
||||
|
||||
使用临时数据库变量展开 Compose 配置,确认默认映射为:
|
||||
|
||||
```text
|
||||
host_ip: 127.0.0.1
|
||||
published: "8080"
|
||||
target: 8080
|
||||
```
|
||||
|
||||
Orbit 的明文业务端口默认只对本机开放,公网入口由反向代理承担。需要直接暴露端口的隔离环境必须显式设置 `ORBIT_HTTP_BIND`,不能把开发配置直接当作生产入口。
|
||||
|
||||
### Nginx 配置语法
|
||||
|
||||
`deploy/nginx/orbit.conf.example` 使用一次性自签名证书挂载到 Nginx 1.27 Alpine 容器中执行:
|
||||
|
||||
```sh
|
||||
nginx -t
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
```text
|
||||
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
||||
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
||||
```
|
||||
|
||||
配置包含 HTTP 到 HTTPS 跳转、TLS 1.2/1.3、`/v1/worker/connect` 和 `/v1/events/connect` 的 Upgrade/Connection 头、独立长连接超时、`/health/live`、`/health/ready` 代理以及 Console 登录来源限速。metrics 不经过业务入口。
|
||||
|
||||
## 尚未由本报告关闭的事项
|
||||
|
||||
本报告只验证配置和端口边界,没有使用真实域名、正式证书、外部负载均衡或公网流量。生产仍需验证证书签发/轮换、DNS、WSS 长连接重连、代理节点故障、真实健康摘除和入口访问日志脱敏;这些不能由一次 `nginx -t` 推导出来。
|
||||
Reference in New Issue
Block a user