Files
Logan.Li 83a3630404
CI / backend (push) Waiting to run
feat(settings): 运行配置中心——.env 业务参数统一到后台页面维护
- 新增 app_configs 表与 appconfig 注册表:读取优先级 页面 → .env → 默认,删除即回退
- 页面可配 7 项:支付回调基址、成功回跳、Webhook 密钥(加密入库)、未验签放行开关、CORS、可信代理、GeoIP 路径
- 引导密钥(JWT_SECRET / OPSLIC_MASTER_KEY / OFFLINE_LICENSE_SEED)与部署参数只读展示掩码+指纹,永不入库
- 校验:URL 格式、密钥长度≥16、CIDR、release 下禁止开启未验签回调;变更写审计日志
- 消费点改造:支付回调地址、Waffo 回跳、webhook 验签、可信代理、CORS、GeoIP 统一走配置中心
- 前端新增「审计与设置 → 运行配置」页(分组表格 + 来源标记 + 编辑弹窗 + 恢复默认)
- .env.example 补注释:哪些必须留在 .env、哪些已收敛到页面
2026-11-01 06:17:58 +08:00

156 lines
7.1 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# opsx-licence - 环境变量配置模板
# 复制此文件为 .env 并根据需要修改
# Docker: cp .env.example .env && ./run.sh docker up
# ============================================
# 后端配置 (backend)
# ============================================
# 服务器端口
PORT=9001
# 运行模式: debug / release(生产 / Docker 请用 release)
GIN_MODE=release
# JWT 密钥(生产环境必须修改!)
JWT_SECRET=your-super-secret-key-change-this-in-production
# 离线许可证签发 seed(32 字节 hex)。生产必须固定;轮换需同步桌面公钥。
# 生成示例: openssl rand -hex 32
# 当前生产公钥(桌面已嵌入): 108375d485c58a1a738f93c2cbb838f76331de981ee5da13d90a1f280672131d
# OFFLINE_LICENSE_SEED=
# 机密字段信封加密主密钥(64 位 hex = 32 字节)。加密 DB 中的支付网关私钥/
# webhook 密钥/节点互联密钥;缺失则启动失败。双节点必须配置相同值!
# 生成示例: openssl rand -hex 32
# OPSLIC_MASTER_KEY=
# 信任代理 CIDR(逗号分隔)。直连公网的节点留空(不信任任何 X-Forwarded-For);
# 经 nginx 反代的节点填反代机器的内网网段,否则限流可被伪造 XFF 绕过。
# 例: TRUSTED_PROXIES=192.168.14.0/24
# TRUSTED_PROXIES=
# 客户端授权防护
# 过期宽限天数(仅商业过期;吊销/暂停无宽限,立即生效)
GRACE_PERIOD_DAYS=15
# 单序列号 24 小时内新设备激活上限(0 = 不限制),抑制换座轮换共享
ACTIVATE_DAILY_LIMIT=5
# 激活记录在线状态有效期(分钟)。默认 8 天,适配客户端周检节奏;
# 如客户端心跳更频繁可调小(如 30 = 在线即 30 分钟内活跃)
ONLINE_TTL_MINUTES=11520
# 解绑是否强制校验设备激活令牌(新激活的设备必须持令牌才能解绑,防偷座)
DEACTIVATE_REQUIRE_TOKEN=true
# 数据库配置
# 可选: sqlite / mysql / postgres
DB_DRIVER=sqlite
# 本地开发可用相对路径;Docker Compose 会覆盖为 /data/db.sqlite3
DB_NAME=db.sqlite3
# MySQL 配置(使用 mysql 时填写)
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_USER=root
# DB_PASSWORD=your-password
# DB_NAME=opsx_licence
# PostgreSQL 配置(使用 postgres 时填写)
# DB_HOST=127.0.0.1
# DB_PORT=5432
# DB_USER=postgres
# DB_PASSWORD=your-password
# DB_NAME=opsx_licence
# CORS 配置(多个用逗号分隔)
# CORS_ORIGINS=http://localhost:5181,http://127.0.0.1:5181
# ============================================
# Waffo 支付(OpsXShell 收银台 · pancake.waffo.ai)
# ============================================
# 店铺: https://pancake.waffo.ai/store/opsxshell-pwsi6m4n
# 包年一次性: PROD_1BIezCi932IbgCzRIV8hcJ (type=onetime, currency=CNY)
# 永久买断: PROD_0pcnzzT4nalEkkcdyIUoD5 (type=onetime, currency=CNY)
# 勿设置单一 WAFFO_CHECKOUT_URL,否则无法按档位分流商品
WAFFO_STORE_SLUG=opsxshell-pwsi6m4n
WAFFO_PRODUCT_ID=PROD_0pcnzzT4nalEkkcdyIUoD5
WAFFO_PRODUCT_ID_YEARLY=PROD_1BIezCi932IbgCzRIV8hcJ
WAFFO_PRODUCT_ID_PERPETUAL=PROD_0pcnzzT4nalEkkcdyIUoD5
WAFFO_CURRENCY=CNY
WAFFO_CURRENCY_YEARLY=CNY
WAFFO_CURRENCY_PERPETUAL=CNY
# test | live(test 时自动附加 test=true;API Key 会话由 Dashboard 环境决定)
WAFFO_ENVIRONMENT=test
# 支付成功回跳(桌面端 deep link;CreateOrder/Checkout 的 return_url 可覆盖)
SUCCESS_URL=https://l123.91ai.io/api/v1/purchase/success
# --- 官方打通必填(API Key 模式,见 https://docs.waffo.ai/zh/integrate/ai-integration)---
# Dashboard → Settings → API Keys:Merchant ID + RSA Private Key
# 有这两项时走 POST /v1/actions/checkout/create-session,并把本系统 ORD-* 写入 orderMerchantExternalId
# 没有则回退到 hosted store URL(无法可靠对账,仅调试用)
# WAFFO_MERCHANT_ID=mch_xxx
# 私钥 PEM(可用真实换行,或把换行写成 \n);勿提交仓库
# WAFFO_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----
# 或 Base64 整段 PEM:
# WAFFO_PRIVATE_KEY_BASE64=
# 兼容旧名:
# WAFFO_PRIVATE_KEY_PEM=
# Dashboard → Settings → Webhooks:
# URL: https://你的域名/api/v1/webhooks/waffo (尽量 HTTPS;Raw JSON;事件 order.completed)
# 当前公网: https://l123.91ai.io/api/v1/webhooks/waffo
# 验签公钥(RSA PEM)或共享密钥;配置后强制校验 X-Waffo-Signature
# WAFFO_WEBHOOK_PUBLIC_KEY=
# WAFFO_WEBHOOK_SECRET=
# 通用回调 /api/v1/webhooks/payment 在 release 下必须配置,并通过 X-Webhook-Secret 传入
# INTERNAL_WEBHOOK_SECRET=
# ============================================
# Docker Compose
# ============================================
# ============================================
# 支付配置(后台「支付配置」页 · 微信支付 / 支付宝)
# ============================================
# 敏感字段(微信 APIv3 密钥、支付宝应用私钥/公钥)不单独设密钥,
# 统一走 internal/secretbox 信封加密,主密钥即上面的 OPSLIC_MASTER_KEY。
# 证书/私钥落地目录(容器内数据卷,位于仓库之外);
# 目录权限 0700、文件 0600,不通过任何静态路由对外暴露。默认 /data/payment-certs
# PAYMENT_CERT_DIR=/data/payment-certs
# 对外基址(用于生成微信/支付宝回调地址展示)
# 已收敛到后台「系统设置 → 运行配置」,此处仅作兜底(页面值优先)
# PAYMENT_PUBLIC_BASE_URL=https://licence.rlwj.cn
# 宿主机映射端口(容器内固定 9001)
HOST_PORT=9001
VERSION=latest
# ============================================
# 前端配置 (frontend)
# ============================================
# 开发环境 API 地址
VITE_API_BASE_URL=http://localhost:9001/api
# 生产环境 API 地址(构建时注入)
# VITE_APP_BASE_API=/api
# ============================================
# 运行配置中心(后台「系统设置 → 运行配置」)
# ============================================
# 读取优先级:app_configs 表(页面) → 环境变量 → 注册表默认值。
# 下面的业务参数建议只在页面维护,.env 里的同名值会被页面值覆盖
# (页面点「恢复默认」即删除库值、回退到这里):
# PAYMENT_PUBLIC_BASE_URL 支付回调对外基址
# SUCCESS_URL 支付成功回跳地址
# INTERNAL_WEBHOOK_SECRET 通用回调验签密钥(页面加密入库)
# ALLOW_UNVERIFIED_WEBHOOK 放行未验签回调(仅调试;release 下页面禁止开启)
# CORS_ORIGINS 跨域白名单(改后需重启)
# TRUSTED_PROXIES 可信反代网段(改后需重启)
# GEOIP_DB_PATH GeoIP 库路径(改后需重启)
#
# 以下引导密钥【必须】留在 .env,页面只读展示指纹,不接受页面写入:
# PORT / GIN_MODE / DB_DRIVER / DB_NAME 进程启动参数(数据库之前就要用)
# JWT_SECRET 直接决定后台登录令牌签发能力
# OPSLIC_MASTER_KEY 解开库内全部密文的根密钥(不入库)
# OFFLINE_LICENSE_SEED 离线授权签名种子(轮换将使旧离线证失效)
# PAYMENT_CERT_DIR 容器内证书目录(数据卷路径)