Skip to content

配置外部服务

FeedLog 可以使用四类可选的外部服务:OAuth 登录、邮件、文件存储和模型接口。不配置这些服务也能运行实例,但相关功能可能会停用或改用备用方式,而且通常不会导致启动报错。下面分别说明需要配置什么、不配置时的实际行为,以及如何判断常见故障。完整的变量清单见代码仓库中的 docs/configuration.md

登录方式

Google 和 GitHub 分别配置。只有同时设置同一组中的两个变量,对应的登录方式才会启用:

bash
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=

登录框只显示配置完整的方式。如果一组变量只设置了其中一个,对应的按钮不会出现。

**不配的话:**默认仍可使用邮箱和密码登录。

只有在没有配置任何 OAuth 服务商时,邮箱密码登录才会自动启用。如果给现有实例添加 Google 或 GitHub,重启后密码登录表单会消失。要同时保留两种登录方式,请设置 AUTH_EMAIL_ENABLED=true

回调地址

在服务商处登记的回调地址必须与 FeedLog 实际发送的地址完全一致:

https://feedback.yourdomain.com/api/auth/callback/google
https://feedback.yourdomain.com/api/auth/callback/github

协议、域名、端口和路径都必须匹配。请使用用户访问 FeedLog 时使用的公开地址。一个 GitHub OAuth App 只能设置一个回调地址,因此预发布环境需要单独创建 App。

在反向代理后面

FeedLog 默认从请求的 Host 头推断对外地址;如果代理设置了 X-Forwarded-Proto,则从该请求头读取协议。FeedLog 不会读取 X-Forwarded-Host。重启后的第一个请求所确定的地址会缓存在当前进程中。

代理保留原始 Host 时,这项推断可以正常工作,Caddy 和 Traefik 默认会这样处理。nginx 只配置 proxy_pass 时会把 Host 替换为上游地址。此后 FeedLog 生成的绝对地址会使用该内网地址,包括 OAuth 的 redirect_uri、密码重置和邮箱验证链接,以及通知邮件中的链接。如果健康检查在首个公开请求之前直接访问容器,FeedLog 也可能缓存容器的内网地址。

可以在代理中保留原始 Host(proxy_set_header Host $host;),也可以显式设置对外地址:

bash
BETTER_AUTH_URL=https://feedback.yourdomain.com

结尾不要带斜杠。对于反向代理后的部署,建议显式设置这个值。

常见错误

Google 报 redirect_uri_mismatch,或者 GitHub 报 "The redirect_uri is not associated with this application" —— 错误页面的地址中包含 FeedLog 发送的 redirect_uri,请将它原样登记。如果该值使用内网地址或以 http 开头,请修改代理配置,而不是 OAuth App。

登录完成后跳到了其他域名 —— FeedLog 推断出了错误的对外地址。请设置 BETTER_AUTH_URL

Google 或 GitHub 的按钮没有出现 —— 对应的一组变量只设置了其中一个。

添加 OAuth 后密码登录消失了 —— 配置 OAuth 后默认会关闭密码登录。请设置 AUTH_EMAIL_ENABLED=true

修改 AUTH_EMAIL_ENABLED 后应用无法启动 —— 如果关闭邮箱登录且没有配置任何 OAuth 服务商,启动检查会失败。注意,空值表示关闭,不表示未设置。

邮件

bash
RESEND_API_KEY=
EMAIL_FROM=[email protected]
EMAIL_PROVIDER=resend   # Optional; Resend is currently the only implemented provider

目前只实现了 ResendEMAIL_PROVIDER 用于按名称选择已注册的服务商,因此设置 RESEND_API_KEY 即可注册 Resend。

请将 EMAIL_FROM 设置为已经通过 Resend 域名验证的发件地址。如果不设置,邮件会使用 Resend 的公共 onboarding 地址发送,而该地址可能只允许向账号所有者本人发送邮件。

FeedLog 会发送以下五类邮件:

邮件什么时候发
邮箱验证有人注册新账号
密码重置有人申请重置
密码已设置用 OAuth 注册的账号新设了密码
工作区邀请管理员邀请成员
通知关注的反馈状态变了,或者收到了管理员的正式回复

通知会发送给关注这条反馈的人,包括作者和投过票的用户;工作区所有者、管理员以及触发该事件的用户除外。只有管理员选择公布状态变更时才会发送通知;仅修改状态不会发送邮件。FeedLog 不发送新反馈或新评论邮件。

**不配的话:**系统不会发送邮箱验证、密码重置和邀请邮件。通知邮件会写入日志,而不会发送给收件人([DEV EMAIL] to=… subject=…,后面跟着链接),并且不会返回错误。无法登录的用户不能通过密码重置恢复访问;管理员需要从成员页面手动复制邀请链接。

AUTH_EMAIL_VERIFY 控制登录前是否必须验证邮箱。未设置时,如果存在 RESEND_API_KEY,邮箱验证会自动启用。设置为 truefalse 可以覆盖默认行为。

常见错误

只有账号所有者能收到邮件,其他人收不到 —— 未设置 EMAIL_FROM,当前使用的是 Resend 的公共 onboarding 发件地址。

没有收到邮件,也没有显示错误 —— 在启动日志中查找 Registered email provider: resend。如果注册的是 console,说明进程没有读取到 RESEND_API_KEY

注册成功后无法登录 —— 设置了 AUTH_EMAIL_VERIFY=true,但没有配置邮件服务。账号已经创建,但系统不会发送验证链接,也不会将链接写入日志,因此无法完成邮箱验证。密码重置也不可用。

邮件中的链接指向了错误的域名 —— FeedLog 从 Host 头推断出了错误的对外地址。请设置 BETTER_AUTH_URL。无法获取这个值时,邀请链接会使用 http://localhost:3000

文件存储

反馈和更新日志支持图片附件,单张图片不能超过 10 MB。存储方式和配置方法取决于部署平台;只有 Docker 和 Node 部署使用 S3_* 变量:

平台存储你要配的
Docker / NodeS3 兼容存储,或本地磁盘S3_*
VercelVercel Blob接一个 Blob store,token 会自动注入
Cloudflare WorkersR2wrangler.toml 里把存储桶绑定为 BLOB

三个变量是必填的,另外两个至少要有一个:

bash
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_BUCKET=feedlog
S3_ENDPOINT=https://<account>.r2.cloudflarestorage.com   # Non-AWS services
S3_REGION=us-east-1                                      # AWS S3

FeedLog 支持 R2、MinIO、Backblaze、Wasabi、阿里云 OSS、腾讯云 COS、七牛等兼容 S3 协议的服务。凭据在运行时读取,因此更换密钥后只需重启应用,不需要重新构建。

存储桶不需要公开可读。文件存储在 <UPLOAD_PREFIX>/<工作区 id>/ 下,并通过 FeedLog 的 /api/files/ 路由读取。UPLOAD_PREFIX 默认为 uploads,可用于区分共用同一存储桶的多个环境。系统会保存每个文件的完整路径,因此以后修改前缀不会影响已有附件。

**在 Docker 上不配的话:**上传文件会写入容器内的 /app/.data/blob。如果 /app/.data 没有挂载卷,删除容器时也会删除这些文件;仓库中的 compose.yml 已包含该挂载。Vercel 和 Workers 不提供本地磁盘备用方案,因此未连接 Blob store 或未绑定 R2 时,上传会失败。

常见错误

上传成功,但重新部署后文件消失 —— 当前使用本地磁盘,而 /app/.data 没有挂载卷。

已经配置 S3,但文件仍写入本地磁盘 —— 只有同时设置 S3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYS3_BUCKET,系统才会注册 S3 服务;缺少变量时不会报错。请确认启动日志中存在 Registered blob provider: s3

S3 disabled: set S3_REGION (for AWS) or S3_ENDPOINT (for R2/MinIO/OSS) —— 已设置三个必填变量,但没有设置 S3_REGIONS3_ENDPOINT,因此驱动无法确定主机名。

上传到阿里云 OSS 失败 —— 阿里云 OSS 可能要求使用 virtual-hosted 风格。保留 S3_BUCKET,并将 S3_ENDPOINT 指向包含 bucket 的域名:https://<bucket>.oss-cn-hangzhou.aliyuncs.com

AI 功能

bash
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_TEXT_MODEL=

OPENAI_API_KEY 决定是否启用 AI 功能。另外两个变量都有默认值,也不会单独生效,因此只设置 base URL 不会启用这些功能。

有三个功能使用模型接口。未配置 key 时,它们的行为如下:

功能没有 key 时
相似反馈检测与搜索改用 trigram 文本匹配
更新日志 AI 起草按钮还在,点下去报错
反馈组件的消息识别消息提交失败

有 key 时,新反馈会生成向量并按语义匹配,因此“用 Google 登不上”可以匹配“SSO 挂了”。没有 key 时,搜索会改用 PostgreSQL 的 trigram 文本距离。系统仍会返回最接近的结果,但只比较文字写法,可能漏掉表述不同的重复反馈。界面不会显示当前使用的是哪种匹配方式。

缺少 key 时,更新日志编辑器仍会显示 AI 起草按钮。管理员选择风格并开始生成后,对话框会显示 AI generation is not configured (OPENAI_API_KEY missing)

反馈组件需要通过模型接口将用户消息转换为结构化反馈。没有 key 时,消息提交会失败,终端用户会看到 Could not send that. Please try again.。启用反馈组件前必须配置这个 key。

关闭 AI 时创建的反馈没有向量,FeedLog 之后也不会自动补充。这些反馈不会参与语义匹配,除非运行仓库中的 scripts/backfill-search.ts 补齐向量。

使用自托管模型接口

OPENAI_BASE_URL 接受兼容 OpenAI API 的接口,包括 LiteLLM 或 vLLM 网关、Ollama,以及其他服务商提供的接口。如果该接口运行在你的网络内,发送给模型的反馈内容也会保留在网络内。

同一个 base URL 同时用于对话请求和向量请求,因此指向单个部署的 Azure URL 只能支持其中一种请求。FeedLog 使用 text-embedding-3-large 请求 768 维向量,数据库字段也要求 768 维。如果接口不能返回这种格式,相似反馈检测会改用 trigram 文本匹配。OPENAI_TEXT_MODEL 只选择对话模型,不影响向量模型。

常见错误

更新日志编辑器显示 "AI generation is not configured" —— 进程没有读取到 OPENAI_API_KEY。在 Workers 上,它是 secret(wrangler secret put OPENAI_API_KEY),不是 [vars] 中的配置项。

添加 key 后,语义相似推荐中仍缺少旧反馈 —— 这些反馈创建时没有生成向量。请运行补齐脚本。

网关在一个功能上返回 404,另一个功能正常 —— base URL 指向了单个部署。请改用可以同时转发 /chat/completions/embeddings 的网关。

反馈组件发送消息失败,界面只显示通用错误 —— 请在服务端日志中查看具体错误。

开源的反馈收集工具。可以自己部署,也可以用我们托管的版本。