环境变量

self-host NSTACK Agents 服务器需要配置的环境变量清单。

NSTACK Agents 的 自部署 服务器启动时从环境变量读取配置——数据库、登录、邮件、存储、注册白名单都在这里配。这一页按用途分组给完整清单:每组说清楚不设会怎样生产必须设哪几个。Auth 相关那几个怎么真正配见 登录与注册配置

核心 server 环境变量

这些是你部署前必须考虑的核心变量——有些有默认值能让 server 启动,但生产环境里你应该显式配置必填项。

环境变量默认值生产必须设?
DATABASE_URLpostgres://concierto:concierto@localhost:5432/concierto?sslmode=disable
PORT8080否(除非换端口)
JWT_SECRETchange-me-in-production(默认值不安全)
APP_ENV(必须 production
FRONTEND_ORIGIN(self-host 要填你自己的域名)
CONCIERTO_DEV_VERIFICATION_CODE否(生产必须保持为空)

生产环境保持 CONCIERTO_DEV_VERIFICATION_CODE 为空。 固定本地测试验证码默认关闭;如果你设置 CONCIERTO_DEV_VERIFICATION_CODE=888888,在 APP_ENV 非 production 时,任何能请求验证码的人都能用这个固定值登录。APP_ENV=production 时该快捷码会被忽略。

数据库连接池

环境变量默认值说明
DATABASE_MAX_CONNS25pgxpool 最大连接数。守护进程高频轮询(每 3 秒)会占用连接;大规模部署可能需要调高
DATABASE_MIN_CONNS5最小常驻连接

不设时使用上表默认值,不是 pgx 内置的 4/NumCPU——后者在生产曾引发连接池耗尽。

怎么配邮件

NSTACK Agents 支持两种邮件发送通道——Resend 适合公网部署,SMTP relay 适合内网/自部署。同时设置时 SMTP_HOST 优先级高于 RESEND_API_KEY

Resend

环境变量默认值说明
RESEND_API_KEYResend API key
RESEND_FROM_EMAILnoreply@nstack.local发件地址(必须是 Resend 账号已验证的域名;走 SMTP 时同时作为 From: 头)

SMTP relay

环境变量默认值说明
SMTP_HOSTSMTP relay 主机名。设置后即启用 SMTP 模式并覆盖 Resend
SMTP_PORT25SMTP 端口。STARTTLS 提交端口用 587暂不支持 465(SMTPS / 隐式 TLS)
SMTP_USERNAMESMTP 用户名。留空表示未认证 relay
SMTP_PASSWORDSMTP 密码
SMTP_TLS_INSECUREfalse设为 true 跳过 TLS 证书校验(仅限私有 CA / 自签证书)

服务端 advertise STARTTLS 时会自动升级。dial 超时 10s,整个 SMTP 会话有 30s deadline,避免 relay 黑洞把 auth handler 挂死。

两种都不设的行为:server 不会报错,但所有本该发出去的邮件(验证码、邀请链接)只打到 server 的 stdout。本地开发方便(你从 server 日志里抄验证码);生产环境忘记设就是黑洞,用户收不到邮件也没任何错误提示。

怎么配 Google OAuth

可选。不设则只有邮箱 + 验证码登录;设了就在登录页出现「用 Google 登录」。

环境变量默认值说明
GOOGLE_CLIENT_IDGoogle Cloud OAuth client ID
GOOGLE_CLIENT_SECRETGoogle Cloud OAuth secret
GOOGLE_REDIRECT_URIhttp://localhost:3000/auth/callbackOAuth 回调地址(self-host 换成你的前端域名)

热生效:前端在运行时通过 /api/config 拿这些配置,改了不用重启前端也不用重建镜像——改完重启 server 即可。

完整配置步骤(含 Google Cloud Console 操作)详见 登录与注册配置

怎么配文件存储

NSTACK Agents 存储用户上传的附件(评论里的图片、文件等)。优先走 S3;不配 S3 就回落本地磁盘。

S3 / S3 兼容存储

环境变量默认值说明
S3_BUCKET只填 bucket 名(例如 my-bucket),不要.s3.<region>.amazonaws.com 后缀——server 会用 S3_BUCKET + S3_REGION 自己拼公开 host。设了就启用 S3 存储
S3_REGIONus-west-2AWS 区域。必须和 bucket 所在区域一致——SDK 签名和公开 URL 都用它
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY静态凭证。全未设时用 AWS SDK 默认凭证链(IAM role / 环境凭证)
AWS_ENDPOINT_URL自定义 S3 兼容端点(例如 MinIO)。设了会切到 path-style URL

S3_BUCKET 未设时:server 启动时打 info 日志 "S3_BUCKET not set, cloud upload disabled",所有上传回落到本地磁盘。

公开 URL 按优先级拼装:

  1. 设了 CLOUDFRONT_DOMAINhttps://<CLOUDFRONT_DOMAIN>/<key>
  2. 设了 AWS_ENDPOINT_URL<AWS_ENDPOINT_URL>/<S3_BUCKET>/<key>(path-style)
  3. 默认走 AWS S3 → https://<S3_BUCKET>.s3.<S3_REGION>.amazonaws.com/<key>(virtual-hosted-style)。bucket 名含点时会回落到 https://s3.<S3_REGION>.amazonaws.com/<S3_BUCKET>/<key>(path-style),因为 AWS 通配证书无法覆盖含点 host。

本地磁盘(S3 未配时)

环境变量默认值说明
LOCAL_UPLOAD_DIR./data/uploads本地存储目录
LOCAL_UPLOAD_BASE_URL空(返回相对路径)公开访问的 base URL——不设前端就拿不到附件的完整 URL

CloudFront(可选)

如果你用 CloudFront 给 S3 做 CDN,三个相关的环境变量:CLOUDFRONT_DOMAINCLOUDFRONT_KEY_PAIR_IDCLOUDFRONT_PRIVATE_KEY(或从 Secrets Manager 读的 CLOUDFRONT_PRIVATE_KEY_SECRET)。不用 CloudFront 就不用管——和配置 S3 不冲突。

环境变量默认值说明
COOKIE_DOMAINsession cookie 的作用域
  • :cookie 只对访问的那个 host 生效(单主机部署正确)
  • 设成 .example.com:cookie 在所有子域共享(让 app.example.comapi.example.com 共用登录态)
  • ⚠️ 不能是 IP 地址(浏览器会忽略)

怎么限制谁能注册

三层白名单按优先级组合。任何一层白名单一旦设置非空,不匹配的邮箱就会被拒——即使 ALLOW_SIGNUP=true 也挡不住。

环境变量默认值说明
ALLOWED_EMAILS显式邮箱白名单(逗号分隔)。非空时只有列表里的邮箱能注册
ALLOWED_EMAIL_DOMAINS域名白名单(逗号分隔)。非空时只有列表里的域名能注册
ALLOW_SIGNUPtrue注册总开关。设 false 完全关闭注册

不直观的点ALLOWED_EMAIL_DOMAINS=company.io + ALLOW_SIGNUP=true 的组合不是「允许 company.io 或所有人」,而是只允许 company.io。白名单的 AND 语义——决策树详见 登录与注册配置 → Signup 白名单

邀请流程本身不检查 signup 白名单——但被邀请人必须先能登录才能接受邀请。如果对方已经有 NSTACK Agents 账号(比如在其他工作区注册过),可以直接接受,不受白名单影响;如果对方还没注册过,他们登录的第一步(发送验证码)仍然会过白名单检查,被 ALLOW_SIGNUP=falseALLOWED_EMAILS / ALLOWED_EMAIL_DOMAINS 拒绝的邮箱无法完成注册,也就没法接受邀请

守护进程的调节参数

守护进程跑在用户本地机器上,配置也是读本地环境变量。常用的几个:

环境变量默认值说明
CONCIERTO_SERVER_URLws://localhost:8080/wsserver 地址(self-host 换成你的域名)
CONCIERTO_DAEMON_HEARTBEAT_INTERVAL15s心跳频率
CONCIERTO_DAEMON_POLL_INTERVAL3s任务轮询频率
CONCIERTO_DAEMON_MAX_CONCURRENT_TASKS20并发任务上限
CONCIERTO_<PROVIDER>_PATH对应 CLI 名各 AI 编程工具的可执行文件路径(如 CONCIERTO_CLAUDE_PATH
CONCIERTO_<PROVIDER>_MODEL各 AI 编程工具的默认模型

完整解释每个参数对守护进程行为的影响,见 守护进程与运行时

前端访问控制

环境变量默认值说明
FRONTEND_ORIGIN前端地址。邀请邮件里的链接、CORS 白名单、cookie domain 都从这里推导。邮件链接在不设时会 fallback 到托管版域名 https://concierto.nstack.ai——self-host 必须显式填
CORS_ALLOWED_ORIGINS额外的 CORS 允许来源(逗号分隔)
ALLOWED_ORIGINSWebSocket 专用的 origin 白名单(逗号分隔);不设就按 CORS_ALLOWED_ORIGINSFRONTEND_ORIGINlocalhost:3000/5173/5174 顺序回落

FRONTEND_ORIGIN 不设就有两个静默失败:(1)邀请邮件里的链接指向 https://concierto.nstack.ai(托管版的域名),用户点了跳不回你的 self-host 实例;(2)WebSocket 连接的 Origin 校验回落到 localhost:3000 / 5173 / 5174,生产部署的 WebSocket 全部被拒,前端看起来「实时更新不工作」。

GitHub 集成

GitHub PR ↔ issue 集成 依赖两个环境变量。两个都配上才会启用 Settings 里的 Connect GitHub 并接受 webhook。

环境变量默认值说明
GITHUB_APP_SLUG你的 GitHub App slug(https://github.com/apps/<slug> 的尾部)。Settings → Integrations 里安装按钮的跳转 URL 用它拼
GITHUB_WEBHOOK_SECRET你在 GitHub App 上设置的 Webhook secret。每条 pull_request / installation delivery 都用它做 HMAC-SHA256 校验;同一个值也用作 setup 回调里 state token 的签名密钥

任一变量未设时:

  • Settings → Integrations 里 Connect GitHub 按钮 disable,对 admin 显示「not configured」提示
  • /api/webhooks/github 直接返回 503 github webhooks not configured——secret 没配置时 NSTACK Agents 拒绝处理任何 webhook 事件,而不是把所有签名当 valid

注意: GITHUB_WEBHOOK_SECRET 同时被复用为 install 流程里 state token 的签名密钥,所以运维只需要维护一个 secret。它不是 GitHub App 的 Client secret——Client secret 是 OAuth 用的,和本集成无关。完整配置流程见 GitHub 集成 → Self-Host 配置

用量统计

默认上报到 NSTACK Agents 官方 PostHog 实例。不想上报就把 ANALYTICS_DISABLED=true

环境变量默认值说明
ANALYTICS_DISABLEDfalsetrue 完全关闭后端上报
POSTHOG_API_KEY内置默认 key换成你自己的 PostHog 实例时填
POSTHOG_HOSThttps://us.i.posthog.com自建 PostHog 的话改成你自己的地址

下一步