配置
Cordy Gateway 的环境变量参考——数据库、Redis、供应商密钥、安全、许可证与运行时行为。
Cordy Gateway 通过环境变量配置。请从 deploy/env.template 开始,它带占位符且不含真实密钥。在生产 Compose 工作流中,.env 提供插值值;下方必需的覆盖文件会把基础生产文件未映射的设置传进容器。
生产环境最少必填项
以下项没有安全默认值,生产部署必须设置:
DB_NAME、DB_USER、DB_PASSWORDDJANGO_SECRET_KEY、DJANGO_ALLOWED_HOSTS、DJANGO_ADMIN_URLCHANNEL_ENCRYPTION_KEYS(Admin 与 Gateway 服务使用相同的值)
生成密钥:
# DJANGO_SECRET_KEY
python -c "import secrets; print(secrets.token_urlsafe(50))"
# CHANNEL_ENCRYPTION_KEYS(一个 Fernet 密钥)
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
数据库
| 变量 | 默认 | 说明 |
|---|---|---|
DB_NAME | — | 数据库名。由 Gateway 数据平面直接读取。 若未设置,Gateway 会回退到一个开发库名,从而无法连上你的生产库。 |
DB_USER | — | 数据库用户。由 Gateway 直接读取。 |
DB_PASSWORD | — | 数据库口令。由 Gateway 直接读取。 |
DB_HOST | postgres(Admin)/ pgbouncer(Gateway) | Gateway 经 PgBouncer 连接;Admin 直连 Postgres。 |
DB_PORT | 5432 | |
DATABASE_URL | — | 仅由 Admin(及迁移/测试工具)使用。Gateway 数据平面不解析 DATABASE_URL;它从 DB_* 构建 DSN。请两者一致设置。 |
陷阱:Gateway 从
DB_NAME/DB_USER/DB_PASSWORD构建 Postgres DSN,而非从DATABASE_URL。若这些在gateway服务上缺失,它会默认到一个开发库名,无法连接,于是每个请求鉴权失败并返回401。请把 Admin 的DB_*值同样配到 Gateway。
Redis
| 变量 | 默认 | 说明 |
|---|---|---|
REDIS_URL | redis://localhost:6379/0 | Redis 连接 URL。在生产 compose 中为 redis://redis:6379/0。 |
REDIS_POOL_SIZE | 20 | 连接池大小。20 是经调优的默认值;随附模板将其提高到 500 以应对高并发。 |
供应商密钥
供应商与通道凭据通常作为 Admin 中加密的 Channel 管理,而非放在环境变量中。以下环境键之所以存在,是因为底层 LiteLLM 集成会自动读取它们;它们是可选的,主要用于开发期播种。生产环境请优先使用按通道的加密凭据。
| 变量 | 供应商 |
|---|---|
OPENAI_API_KEY | OpenAI |
ANTHROPIC_API_KEY | Anthropic |
OPENROUTER_API_KEY | OpenRouter |
GEMINI_API_KEY | Google Gemini |
AZURE_API_KEY、AZURE_API_BASE、AZURE_API_VERSION | Azure OpenAI |
AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION_NAME | AWS Bedrock |
COHERE_API_KEY | Cohere |
GROQ_API_KEY | Groq |
TOGETHERAI_API_KEY | Together AI |
DEEPINFRA_API_KEY | DeepInfra |
REPLICATE_API_TOKEN | Replicate |
HUGGINGFACE_API_KEY | Hugging Face |
通道与凭据如何工作见供应商。
安全
| 变量 | 默认 | 说明 |
|---|---|---|
CHANNEL_ENCRYPTION_KEYS | — | 逗号分隔的 Fernet 密钥,用于静态加密通道上游凭据。第一个为活跃(加密)密钥,其余用于轮换。生产必填——Admin 与 Gateway 缺少它都会拒绝启动,且两者必须使用相同的值。 |
CLIENT_CORS_ORIGINS | 空 | 允许从浏览器调用 Gateway 的 Origin,逗号分隔。为空则拒绝所有跨源浏览器访问(服务器到服务器的调用方不使用 CORS)。字面量 * 在生产环境启动时被拒绝。 |
CLIENT_CORS_ALLOW_WILDCARD_IN_PRODUCTION | false | 允许生产环境使用 * 客户端 CORS 源的不安全逃生阀。请保持关闭。 |
TRUSTED_PROXY_CIDRS | 空 | 受信反向代理的 CIDR。仅当 socket 对端匹配其一时,才为记录的客户端 IP 采信 X-Forwarded-For / X-Real-IP;否则使用 socket 对端。防止审计 IP 伪造。 |
GATEWAY_METRICS_TOKEN | 空 | 抓取器访问 /metrics/prometheus 必须出示的 bearer 令牌。生产端点经公开 nginx 访问时使用此项。它与允许 CIDR 均为空时,生产环境返回 403。 |
GATEWAY_METRICS_ALLOWED_CIDRS | 空 | 无需令牌即可抓取的 CIDR。检查使用直接 socket 对端,且先于令牌校验。位于公开 nginx 之后时,允许 nginx 或其网络也会放行它代理的公共请求;请留空。CIDR 仅用于直接、隔离的受信抓取路径。 |
DJANGO_SECRET_KEY | — | Django 加密密钥(Admin)。生产必填。 |
DJANGO_ALLOWED_HOSTS | — | Admin 服务的主机名,逗号分隔。生产必填。 |
DJANGO_ADMIN_URL | — | Admin URL 路径前缀;必须以 / 结尾。取不显而易见的值。生产必填。 |
DJANGO_CSRF_TRUSTED_ORIGINS | 空 | TLS 代理之后允许向 Admin POST 的、带协议的源(例如 https://admin.example.com)。 |
DJANGO_SECURE_SSL_REDIRECT | True | 强制 HTTP→HTTPS 跳转。仅本地无 TLS 测试才设 False。 |
ADMIN_HTTP_PORT | 8001 | Admin 发布的主机端口。 |
GATEWAY_HTTP_PORT | 8002 | Gateway(经 nginx)发布的主机端口。 |
Admin 与成员门户
| 变量 | 默认值 | 说明 |
|---|---|---|
CORDY_GATEWAY_BASE_URL | http://127.0.0.1:8002/v1 | /my/ 成员快速开始中显示的基础 URL。生产环境应设为客户端可访问的 HTTPS URL;它不会改变 Gateway 监听地址。 |
ADMIN_LANGFUSE_TRACE_URL_TEMPLATE | 空 | Request logs 与成员用量中的可选外部追踪链接。必须是包含字面量 {trace_id} 的 HTTP(S) URL,例如 https://langfuse.example.com/trace/{trace_id}。 |
两者都是 Admin 进程变量,必须通过下方部署覆盖文件传入。
必需的生产 Compose 覆盖文件
docker-compose.prod.yml 没有把 .env 作为容器的 env_file 加载。--env-file .env 只为 ${...} 提供插值,而基础文件没有把 ENVIRONMENT 或下列安全与运行时变量映射进 gateway。因此只用基础文件时,Gateway 会采用 development 默认值:空 CORS 列表回退为 *;未设置指标令牌/CIDR 时指标公开;.env 中未被引用的调优值无效;信用扣减 WAL 保持关闭。
在基础文件旁创建 docker-compose.production-overrides.yml。它修正实际部署配置,但不会更改上游 docker-compose.prod.yml:
services:
admin:
environment:
CORDY_GATEWAY_BASE_URL: ${CORDY_GATEWAY_BASE_URL:?set CORDY_GATEWAY_BASE_URL}
ADMIN_LANGFUSE_TRACE_URL_TEMPLATE: ${ADMIN_LANGFUSE_TRACE_URL_TEMPLATE:-}
gateway:
environment:
ENVIRONMENT: production
CLIENT_CORS_ORIGINS: ${CLIENT_CORS_ORIGINS:-}
CLIENT_CORS_ALLOW_WILDCARD_IN_PRODUCTION: ${CLIENT_CORS_ALLOW_WILDCARD_IN_PRODUCTION:-false}
TRUSTED_PROXY_CIDRS: ${TRUSTED_PROXY_CIDRS:-}
GATEWAY_METRICS_TOKEN: ${GATEWAY_METRICS_TOKEN:-}
GATEWAY_METRICS_ALLOWED_CIDRS: ${GATEWAY_METRICS_ALLOWED_CIDRS:-}
GATEWAY_DEFAULT_ROUTING_STRATEGY: ${GATEWAY_DEFAULT_ROUTING_STRATEGY:-weighted}
GATEWAY_MAX_BODY_BYTES: ${GATEWAY_MAX_BODY_BYTES:-10485760}
GATEWAY_MAX_INFLIGHT_PER_KEY: ${GATEWAY_MAX_INFLIGHT_PER_KEY:-50}
GATEWAY_DEFAULT_MAX_COMPLETION_TOKENS: ${GATEWAY_DEFAULT_MAX_COMPLETION_TOKENS:-4096}
GATEWAY_PRICE_TTL_SECONDS: ${GATEWAY_PRICE_TTL_SECONDS:-300}
IDEMPOTENCY_TTL_SECONDS: ${IDEMPOTENCY_TTL_SECONDS:-600}
GATEWAY_CREDIT_CONSUME_WAL: /var/lib/cordy/credit-consume.jsonl
OTEL_TRACING_ENABLED: ${OTEL_TRACING_ENABLED:-false}
OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-cordy-gateway}
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
OTEL_EXPORTER_OTLP_HEADERS: ${OTEL_EXPORTER_OTLP_HEADERS:-}
OTEL_SHUTDOWN_TIMEOUT_SECONDS: ${OTEL_SHUTDOWN_TIMEOUT_SECONDS:-2.0}
volumes:
- gateway_wal:/var/lib/cordy
volumes:
gateway_wal:
在 .env 设置 CORDY_GATEWAY_BASE_URL=https://gateway.example.com/v1;使用 Langfuse 时再设置 ADMIN_LANGFUSE_TRACE_URL_TEMPLATE=https://langfuse.example.com/trace/{trace_id}。拓扑需要时还应设置显式浏览器 Origin 与受信代理 CIDR。公开 nginx 部署应设置强 GATEWAY_METRICS_TOKEN 并让 GATEWAY_METRICS_ALLOWED_CIDRS 保持为空;CIDR 检查看到的是 nginx,而非原始公共客户端。
每次启动、重建或扩容时都应用两个文件:
docker compose \
-f docker-compose.prod.yml \
-f docker-compose.production-overrides.yml \
--env-file .env up -d
具名卷会让 /var/lib/cordy/credit-consume.jsonl 在容器替换后继续存在。随附 Gateway 镜像没有声明 USER,因此以 root 运行并可写入挂载目录。如果你用自定义 UID 重新分发镜像,必须创建 /var/lib/cordy 并授予该 UID 写权限;应用会直接打开目标文件,不会创建缺失的父目录。
Redis 信用扣减缓冲写入失败时,Gateway 会把 JSON Lines 成本记录追加到该 WAL,并让请求继续完成。若路径为空或追加也失败,则会记录 consume_drop_total 对应的少扣款。仓库没有自动 WAL 重放命令。请保留该文件作为计费证据,并与请求日志、信用流水和上游账单核对后再人工调整;不要把它交给未记录的命令。
许可证
Cordy Gateway 使用离线的、HMAC 签名的许可证。许可证默认为仅审计(fail-open);它不会阻断正常部署。
| 变量 | 默认 | 说明 |
|---|---|---|
LICENSE_KEY | 空 | HMAC 签名的许可证载荷。未授权/开发时留空。 |
LICENSE_SIGNING_SECRET | 空 | 用于校验许可证的共享密钥,按客户提供。 |
LICENSE_CUSTOMER_ID | 空 | 匹配载荷的预期客户 id;留空则跳过。 |
LICENSE_NODE_ID | node-1 | 用于节点数校验的当前节点 id。 |
LICENSE_ENFORCEMENT_MODE | audit_only | audit_only(fail-open,仅记录)或 strict(fail-closed)。 |
运行时行为
| 变量 | 默认 | 说明 |
|---|---|---|
GATEWAY_DEFAULT_ROUTING_STRATEGY | weighted | 默认通道选择策略:weighted、cheapest、fastest 或 region_aware。可用 X-Routing-Strategy 按请求覆盖。 |
GATEWAY_MAX_BODY_BYTES | 10485760(10 MiB) | 请求体硬上限。更大的请求体得到 413。<= 0 关闭该上限。 |
GATEWAY_MAX_INFLIGHT_PER_KEY | 50 | 每 API 密钥的最大在途并发请求数。<= 0 关闭。 |
GATEWAY_DEFAULT_MAX_COMPLETION_TOKENS | 4096 | 当请求未设置 max_tokens 时,用于配额准入的补全令牌估算值。 |
GATEWAY_PRICE_TTL_SECONDS | 300 | 成本快照所用有效价格缓存的每进程 TTL。 |
GATEWAY_CREDIT_CONSUME_WAL | 空 | Redis 缓冲写入失败时用于信用扣减成本的追加式 JSON Lines 备份。生产覆盖文件设置持久路径;路径为空或不可写时可能留下已计数的少扣款。 |
GRANIAN_WORKERS | 8 | 每个 Gateway 容器的 Granian worker 进程数。 |
IDEMPOTENCY_TTL_SECONDS | 600 | 已存幂等响应 / 锁的存活时间。 |
可观测性(OpenTelemetry)
追踪默认关闭。生产覆盖文件会把所有受支持的 OTEL_* 字段映射进 gateway。请配置一个 Gateway 容器可达、由运维管理的 OTLP/HTTP collector:
OTEL_TRACING_ENABLED=true
OTEL_SERVICE_NAME=cordy-gateway
OTEL_EXPORTER_OTLP_ENDPOINT=https://telemetry.example.com/v1/traces
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <collector-token>"
OTEL_SHUTDOWN_TIMEOUT_SECONDS=2.0
把更新后的环境应用到 Gateway:
docker compose \
-f docker-compose.prod.yml \
-f docker-compose.production-overrides.yml \
--env-file .env up -d gateway
随附的 docker-compose.tracing.yml 与 docker-compose.observability.yml 是开发/参考配置。其 collector 所在网络没有接入生产 Gateway,且 observability 配置带 CHANGEME 默认值。若未另外设计并验证网络、密钥、存储与访问控制,不要把它们与生产技术栈组合。
| 变量 | 默认 | 说明 |
|---|---|---|
OTEL_TRACING_ENABLED | false | 为 Gateway 启用 OpenTelemetry 追踪。 |
OTEL_SERVICE_NAME | cordy-gateway | 追踪中上报的 service.name。 |
OTEL_EXPORTER_OTLP_ENDPOINT | 空 | 导出追踪的 OTLP HTTP 端点。 |
OTEL_EXPORTER_OTLP_HEADERS | 空 | 逗号分隔的 OTLP 导出器请求头。 |
OTEL_SHUTDOWN_TIMEOUT_SECONDS | 2.0 | 关闭时有界的 flush 超时。 |
扩展与基础设施
以下项用于调优 compose 技术栈与横向扩展。见部署。
| 变量 | 默认 | 说明 |
|---|---|---|
SCALE_GRANIAN_WORKERS | 4 | 运行多个网关副本时的每副本 worker 数。 |
ADMIN_WORKERS | 3 | Admin 服务的 Gunicorn worker 数。 |
PGBOUNCER_POOL_SIZE | 100 | PgBouncer 默认池大小。 |
PGBOUNCER_MAX_CLIENT_CONN | 400 | PgBouncer 最大客户端连接数。 |
REDIS_MAXMEMORY | 512mb | Redis 最大内存(采用永不触及资金键的 volatile-lru 驱逐)。 |
备份
| 变量 | 默认 | 说明 |
|---|---|---|
BACKUP_DIR | 脚本中为 ./backups | 逻辑备份写入位置。生产模板推荐 /var/backups/cordy。 |
BACKUP_RETENTION | 7 | 保留的备份数量。 |
REQUIRE_PITR | 0 | 一旦启用 WAL 归档 / 时间点恢复,设为 1 以在验收检查中强制它。 |