Accent v1.32.1 配置参数详解
Accent v1.32.1 全量环境变量与 config/runtime.exs 配置项详解:数据库、端口与反代、密钥、SMTP、OAuth/OIDC、多项目角色权限、机器翻译与可观测性、日志级别;含 8 项参数改值实测回显与 DEBUG_ERRORS 编译期陷阱等排障实录。
Accent v1.32.1 配置参数详解
目标:把 Accent v1.32.1 的全部运行期配置讲清楚——每个变量的读取位置、类型、默认值、真实效果,以及哪些「官方 README 写了但代码里根本没有」。全文基于 v1.32.1 的
config/runtime.exs、lib/accent/config.ex源码,并在 Ubuntu 22.04 + OTP Release 实例上逐项改值验证,回显照抄。
一、先厘清三件事
1.1 变量名没有 ACCENT_ 前缀
很多部署笔记写成 ACCENT_DATABASE_URL、ACCENT_SECRET_KEY_BASE,这在 v1.32.1 上不生效。实测在源码全量检索 ACCENT_,唯一命中是 S3 集成执行时拼进请求头的 ACCENT_VERSION=... 字符串,与配置无关:
grep -rn "ACCENT_" lib config rel
# 回显(仅一条):
# lib/accent/integrations/execute/aws_s3.ex:44: "ACCENT_VERSION=..."}
配置变量就是裸名:DATABASE_URL、PORT、SECRET_KEY_BASE、SMTP_ADDRESS 等。加前缀不会报错,但会被静默忽略——这是最常见的「配了却没生效」原因。
1.2 所有变量都在 config/runtime.exs 读取
Accent 遵循 Twelve-Factor,runtime.exs 在每个节点启动时执行,因此同一份 Release 产物可以靠环境变量切换环境。编译期配置(config/prod.exs)只保留少量固定项,两者的边界见第十一节。
1.3 类型解析规则
Accent.Config.get_env/2 是唯一入口,支持 6 种类型:
| 类型 | 解析规则 | 典型变量 |
|---|---|---|
:string(默认) | 原样返回,未设置为 nil | CANONICAL_URL、MAILER_FROM、OAuth 各 *_CLIENT_ID |
:integer | String.to_integer/1,非法值直接抛异常,启动失败 | PORT、DATABASE_POOL_SIZE、DATABASE_TIMEOUT |
:boolean | "true"/"1"(忽略大小写)为真,其余为假 | DATABASE_SSL、DISABLE_CANONICAL_HOST_REDIRECT、ECTO_IPV6 |
:uri | URI.parse/1,空串视为 nil | CANONICAL_URL、STATIC_URL |
:comma_separated_list | 按逗号切分,未设置返回 [] | LANGUAGE_TOOL_LANGUAGES |
:cors | 单值或逗号分隔列表 | 预留 |
⚠️ 关键陷阱:布尔型变量走
:boolean解析("0"/"false"为假),但功能开关型变量(DUMMY_LOGIN_ENABLED、SENTRY_DSN、SMTP_ADDRESS、TZDATA_AUTOUPDATE_DISABLED等)在runtime.exs里用的是if get_env("XXX")直接判空。Elixir 中空字符串""是真值,因此DUMMY_LOGIN_ENABLED=0、=false、甚至=空值都会开启功能,只有「完全不存在这个变量」才会关闭。详见第七节实测。
二、配置生效的三种验证手段
不要靠「重启了应该就好了」判断配置是否生效,用下面三种手段拿回显。
手段一:systemd EnvironmentFile(生产推荐)
# /etc/accent/accent.env
PORT=4000
DATABASE_URL=postgresql://accent:q1w2e3r4@127.0.0.1:5432/accent_prod
SECRET_KEY_BASE=<64 字节随机串>
# /etc/systemd/system/accent.service
[Service]
EnvironmentFile=/etc/accent/accent.env
ExecStart=/opt/accent-release/bin/accent start
手段二:bin/accent eval 读运行期配置(本文主要手段)
Release 自带 eval 子命令,不启动业务进程,但会执行 runtime.exs,所以能把「环境变量 → 应用配置」的真实映射打印出来:
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:accent, Accent.Endpoint)[:http], label: "endpoint_http")'
手段三:启动日志与接口。端口、LanguageTool、迁移结果都会在启动时打印;认证提供商可通过 GraphQL 查询。
三、数据库配置
| 变量 | 默认值 | 作用 | 实测 |
|---|---|---|---|
DATABASE_URL | postgres://localhost/accent_development | Ecto 连接串,postgresql://用户:口令@主机:端口/库名 | ✔ |
DATABASE_SSL | false | 是否启用 SSL 连接 | 源码依据 |
DATABASE_POOL_SIZE | 未设置时用 Ecto 默认 10(README 标注 10) | 连接池大小 | ✔ 改 25 生效 |
DATABASE_TIMEOUT | 29000 | 单次查询超时(毫秒) | ✔ 改 15000 生效 |
DATABASE_QUEUE_TARGET | 500 | 排队等待获取连接的毫秒阈值 | 源码依据 |
DATABASE_QUEUE_INTERVAL | 2000 | 队列检查间隔(毫秒) | 源码依据 |
ECTO_IPV6 | false | 为真时 socket 加 :inet6,用于纯 IPv6 内网 | 源码依据 |
验证(把池调到 25、超时调到 15000 后执行):
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:accent, Accent.Repo)[:pool_size], label: "db_pool_size");
IO.inspect(Application.get_env(:accent, Accent.Repo)[:timeout], label: "db_timeout")'
# 回显:
# db_pool_size: 25
# db_timeout: 15000
⚠️ 注意:
runtime.exs里ssl_opts: [verify: :verify_none],即开启DATABASE_SSL也不校验证书。跨公网连库时应改走内网/专线或自行在源码中收紧该选项,不要仅依赖 SSL 打开。⚠️
DATABASE_POOL_SIZE与DATABASE_QUEUE_*是:integer解析,DATABASE_POOL_SIZE=25(末尾空格)会抛ArgumentError直接启动失败;同理DATABASE_URL必须带协议头,写成user:pass@host/db会被 Ecto 拒绝。
四、站点、端口与反向代理
| 变量 | 默认值 | 作用 | 实测 |
|---|---|---|---|
PORT | 4000 | HTTP 监听端口 | ✔ 改 8080 生效 |
CANONICAL_URL | http://localhost:<PORT> | 站点对外 URL,用于邮件链接、OAuth 回调、静态资源域名 | ✔ |
STATIC_URL | 等于 CANONICAL_URL | 静态资源对外 URL,前后端分离/CDN 时单独设置 | 源码依据 |
DISABLE_CANONICAL_HOST_REDIRECT | false | 关闭「非规范域名 301 到 CANONICAL_URL」 | ✔ |
DISABLE_FRAME_ANCESTORS | false | 为真时输出 frame-ancestors 'self',禁止被第三方页面内嵌(同时会使 JIPT 无法嵌入你的站点) | 源码依据 |
WEBAPP_SKIP_SUBRESOURCE_INTEGRITY | false | 去掉 link/script 的 SRI 属性,适用于会改写静态资源的代理 | 源码依据 |
DEBUG_ERRORS | false(编译期固定) | 错误页是否显示详情 | ❌ 运行期改为 true 直接启动失败,见 11.2 |
实测端口变更:
# 测试实例监听 8080,宿主机 8134 转发到 8080
grep -E 'Running Accent|Access Accent' /var/log/accent.log
# 回显:
# [info] Running Accent.Endpoint with Bandit 1.13.0 at 0.0.0.0:8080 (http)
# [info] Access Accent.Endpoint at http://localhost:8134
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:8134/
# 回显:HTTP 200
4.1 FORCE_SSL 是个「文档变量」
官方 README 的 Production setup 表里有 FORCE_SSL,但 v1.32.1 源码中检索不到该变量:
grep -rn "FORCE_SSL" config lib rel
# 回显:空
真实逻辑在 runtime.exs:
force_ssl: get_uri_part(canonical_uri, :scheme) === "https"
即 HTTPS 由 CANONICAL_URL 的 scheme 推导:写 https:// 就自动开 SSL 重定向,写 http:// 就关。设置 FORCE_SSL=true 不会有任何效果。
4.2 反向代理的标准写法
TLS 在 Nginx 终结时:
location / {
proxy_pass http://127.0.0.1:4000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; # GraphQL Subscription/WebSocket
}
同时设置 CANONICAL_URL=https://your.domain、DISABLE_CANONICAL_HOST_REDIRECT=1。若不加后者,健康检查常用 IP 直连会被 301 到规范域名,表现为「服务 active 但探活一直 301」。实测把 CANONICAL_URL 设为 https:// 且不加该开关时,直连 IP 的请求会被 Plug.SSL 重定向。
五、密钥与加密
| 变量 | 默认值 | 作用 |
|---|---|---|
SECRET_KEY_BASE | UNSAFE_pJhJ9q2q... | 会话 Cookie 加密与签名主密钥 |
SIGNING_SALT | accent-signing-salt-used-for-callback-auth | Cookie 与 OAuth 回调签名盐 |
MACHINE_TRANSLATIONS_VAULT_KEY | DEFAULT_UNSAFE_VAULT_KEY | 机器翻译/AI 密钥的加密主密钥(Cloak) |
SECRET_KEY_BASE生成:openssl rand -hex 64(64 字节)。必须固定,重启换值会导致所有用户会话失效、OAuth 回调校验失败。- 默认值是公开的
UNSAFE_*字符串,生产不替换等于没有加密。 MACHINE_TRANSLATIONS_VAULT_KEY用于加密项目里保存的 Google/DeepL/OpenAI 密钥。换这个值后,数据库里已存的密文无法解密,表现为「机器翻译配置页能打开但翻译报密钥错误」,必须在项目设置里重新录入密钥。轮换前先评估。
六、邮件配置
runtime.exs 用 cond 决定邮件适配器,优先级从高到低:
| 顺序 | 触发变量 | 适配器 |
|---|---|---|
| 1 | SENDGRID_API_KEY | Bamboo.SendGridAdapter |
| 2 | MANDRILL_API_KEY | Bamboo.MandrillAdapter |
| 3 | MAILGUN_API_KEY(+MAILGUN_DOMAIN、MAILGUN_BASE_URI) | Bamboo.MailgunAdapter |
| 4 | SMTP_ADDRESS(+SMTP_PORT、SMTP_USERNAME、SMTP_PASSWORD) | BambooSMTPAdapterWithTlsOptions |
| 5 | 都不配 | Bamboo.LocalAdapter(只写日志,不投递) |
通用项:
| 变量 | 作用 |
|---|---|
MAILER_FROM | 发件人地址,未设置时邮件头为空,多数 SMTP 会拒收 |
SMTP_API_HEADER | 附加到邮件的自定义头(如 SendGrid 分类) |
实测把 SMTP 指向内网投递端后读取配置:
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:accent, Accent.Mailer), label: "mailer")'
# 回显:
# mailer: [
# mailer_from: "accent-noreply@example.com",
# x_smtpapi_header: nil,
# adapter: BambooSMTPAdapterWithTlsOptions,
# server: "10.89.61.1",
# port: "2525",
# username: "accent",
# password: "q1w2e3r4"
# ]
同版本实例向 SMTP 接收端发送邀请邮件,接收端日志回执:
2026-10-27T18:55:58 ... >> '250 OK queued'
...
<a ... href="http://localhost:8133/">http://localhost:8133/</a>
两点结论:投递通路可用;邮件正文里的链接来自 CANONICAL_URL,域名配错会直接导致邀请链接打不开。
⚠️ 注意:
SMTP_PORT在配置结构里是字符串(回显port: "2525"),不是整数。v1.32.1 的适配器接受字符串,但如果你自行写脚本读取该配置并参与数值比较,需要先String.to_integer/1。⚠️ 优先级是「谁先命中谁生效」:同时配了
SENDGRID_API_KEY和SMTP_ADDRESS时,SMTP 被静默忽略。
七、认证与单点登录
runtime.exs 按「命中即追加」的方式构造 Ueberauth 提供商列表,最终顺序与代码书写顺序相反(后写的在前):
| 变量组 | 提供商 | 备注 |
|---|---|---|
GOOGLE_API_CLIENT_ID/_SECRET | scope email openid | |
SLACK_CLIENT_ID/_SECRET(+SLACK_TEAM_ID) | Slack | |
GITHUB_CLIENT_ID/_SECRET | GitHub | scope user |
GITLAB_CLIENT_ID/_SECRET(+GITLAB_SITE_URL) | GitLab | 自建 GitLab 必须改 GITLAB_SITE_URL,否则回调去 gitlab.com |
DISCORD_CLIENT_ID/_SECRET | Discord | |
MICROSOFT_CLIENT_ID/_SECRET(+MICROSOFT_TENANT_ID) | Microsoft | 租户 ID 决定单租户/多租户 |
AUTH0_CLIENT_ID/_SECRET(+AUTH0_DOMAIN) | Auth0 | |
OIDC_CLIENT_ID/_SECRET(+OIDC_ISSUER、OIDC_SCOPE、OIDC_UID_FIELD) | 通用 OIDC | 回调路径 /auth/oidc/callback |
DUMMY_LOGIN_ENABLED | Dummy | 只填邮箱、无密码登录 |
OIDC 的两个细节:
OIDC_ISSUER推荐使用,值形如https://idp.example.com/realms/xxx;OIDC_DISCOVERY_URI已废弃但仍兼容,代码会裁掉/.well-known/openid-configuration后缀。OIDC_UID_FIELD默认sub;若 IdP 用preferred_username做唯一标识可改,但同一用户换字段会产生重复账号。
实测只开 Dummy 登录后:
curl -s -X POST http://127.0.0.1:8134/graphql \
-H "Authorization: Bearer <API_TOKEN>" -H 'Content-Type: application/json' \
-d '{"query":"{ authenticationProviders { id } }"}'
# 回显:{"data":{"authenticationProviders":[{"id":"dummy"}]}}
⚠️ 再次强调空值陷阱:把
DUMMY_LOGIN_ENABLED写成0或false想关掉它是无效的,""在 Elixir 里是真值。生产上线前必须删除该变量,而不是置 0。GitHub/Google 等提供商同理——只要变量存在(哪怕空串),登录按钮就会出现,随后因 client_id 为空而报错。
7.1 限制谁能建项目
| 变量 | 作用 |
|---|---|
RESTRICTED_PROJECT_CREATOR_EMAIL_DOMAIN | 只允许该邮箱域的用户创建新项目,已存在项目不受影响 |
RESTRICTED_DOMAIN | 同上,旧别名,二者取其一即可(前者优先) |
实测设为 example.com:
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:accent, :restricted_domain), label: "restricted_domain")'
# 回显:restricted_domain: "example.com"
八、多租户与角色权限
Accent 的「多租户」是单实例多项目模型,不是每租户一套库表:
- 用户(
users)全局唯一,可同时属于多个项目; - 项目(
projects)是数据隔离边界:文档、版本、翻译、评审、集成、API Token 全部挂在项目下; - 项目成员关系存在
collaborators,角色是项目级的,同一个人在不同项目可以角色不同; - 没有「组织/工作区」层级,跨项目汇总要靠 API 或自行聚合。
角色共 5 + 1 个,源码定义在 lib/accent/schemas/role.ex,GraphQL 枚举回显为大写:
curl -s -X POST http://127.0.0.1:8134/graphql \
-H "Authorization: Bearer <API_TOKEN>" -H 'Content-Type: application/json' \
-d '{"query":"{ roles { slug } }"}'
# 回显:
# {"data":{"roles":[{"slug":"OWNER"},{"slug":"ADMIN"},{"slug":"DEVELOPER"},
# {"slug":"REVIEWER"},{"slug":"TRANSLATOR"}]}}
权限是累加式(RoleAbilities 里逐层 ++),实测矩阵:
| 能力 | translator | reviewer | developer | admin | owner | bot |
|---|---|---|---|---|---|---|
| 只读(翻译/文档/版本/评论/活动) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| 编辑翻译、增删评论、处理 lint、订阅通知 | ✔ | ✔ | ✔ | ✔ | ✔ | ✘ |
| 标记已评审/取消评审、批量修正 | ✘ | ✔ | ✔ | ✔ | ✔ | ✘ |
| 同步/合并、文档增删改、API Token、集成、版本、机器翻译配置、Prompt | ✘ | ✘ | ✔ | ✔ | ✔ | 仅 sync/merge |
| 项目设置/删除、成员增删改、回滚、锁定文件操作 | ✘ | ✘ | ✘ | ✔ | ✔ | ✘ |
bot 角色不在 roles 查询结果里,它是 API Token 专用的受限角色:只读 + 同步/合并,无法修改翻译内容——给 CI/CD 用这个角色最安全。
💡 技术拓展:这套模型和 Weblate 的「项目/组件 + 角色」接近,但比 Transifex 的「组织-团队-项目」三层少一层。需要租户级硬隔离(客户之间互不可见、独立备份)时,不要试图在 Accent 内用项目模拟,应按客户拆实例/拆库,再在上层做统一入口。
九、机器翻译、AI 与拼写检查
| 变量 | 作用 | 默认 |
|---|---|---|
GOOGLE_TRANSLATIONS_SERVICE_ACCOUNT_KEY | Google 翻译服务账号 JSON | 无 |
DEEPL_TRANSLATIONS_KEY | DeepL API Key | 无 |
OPENAI_API_KEY | AI 助手/Prompt 能力的 OpenAI Key | 无 |
OPENAI_API_MODEL | 模型名 | gpt-4o |
OPENAI_API_BASE_URL | 兼容 OpenAI 协议的网关地址 | https://api.openai.com/v1/ |
AI_ASSISTANT_USE_DEFAULT_PROVIDER | 是否默认启用内置 AI 提供商 | 无 |
LANGUAGE_TOOL_LANGUAGES | 拼写检查语言,逗号分隔,如 fr,en | [] |
这些密钥在项目设置里也可逐项目配置,环境变量提供的是「默认值」,且会被 MACHINE_TRANSLATIONS_VAULT_KEY 加密后落库。
实测开启拼写检查:
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:accent, LanguageTool), label: "languagetool")'
# 回显:languagetool: [languages: ["fr", "en"]]
启动日志会等语言包预热完成才宣告就绪(实测约 3 秒):
[info] LanguageTool is ready to spellcheck languages: fr, en (started in 2972ms)
未配置时是提示而非错误:
[info] LanguageTool was not configured. Use LANGUAGE_TOOL_LANGUAGES environment variable to set a list of comma-separated languages short code.
⚠️ 语言包首次加载依赖网络下载时,内网环境会卡在启动阶段;建议预热后再切流量,或接受「前几秒拼写检查不可用」。
十、可观测性
| 变量 | 作用 |
|---|---|
SENTRY_DSN | 后端运行时错误上报(含 SENTRY_ENVIRONMENT_NAME,默认 production) |
WEBAPP_SENTRY_DSN | 前端错误上报(公钥 DSN) |
NEW_RELIC_APP_NAME / NEW_RELIC_LICENSE_KEY | NewRelic APM |
OTEL_EXPORTER_OTLP_ENDPOINT | 设置后启用 OTLP 链路导出(Phoenix/Absinthe/Ecto/Oban/Bandit/Tesla) |
OTEL_EXPORTER_OTLP_HEADERS / OTEL_RESOURCE_ATTRIBUTES | 导出头与资源属性 |
TZDATA_AUTOUPDATE_DISABLED | 关闭时区库自动更新,只读文件系统必设 |
runtime.exs 里只有 OTEL_EXPORTER_OTLP_ENDPOINT 参与判断,未设置时显式 traces_exporter: :none。README 列出的 OTEL_EXPORTER_OTLP_PROTOCOL 在源码中检索不到:
grep -rn "OTEL_EXPORTER_OTLP_PROTOCOL" config lib rel
# 回显:空
需要 gRPC 导出时应以你所使用的 exporter 版本默认行为为准,不要指望这个变量。
十一、日志级别:为什么改了没用
11.1 级别是编译期写死的
config/prod.exs:
config :logger, :console,
format: "$time $metadata[$level] $message\n",
level: :info,
metadata: ~w(request_id current_user graphql_operation hook_service hook_url)a
全仓库检索 LOG_LEVEL 无任何命中:
grep -rn "LOG_LEVEL" config lib rel
# 回显:空
运行期确认:
/opt/accent-release/bin/accent eval \
'IO.inspect(Application.get_env(:logger, :console), label: "logger_console")'
# 回显:
# logger_console: [
# format: "$time $metadata[$level] $message\n",
# level: :info,
# metadata: [:request_id, :current_user, :graphql_operation, :hook_service, :hook_url]
# ]
结论:v1.32.1 没有 LOG_LEVEL 环境变量。想调级别只有两条路:
- 改
config/prod.exs的level: :debug,重新mix release(官方发行版产物做不到); - 运行期用
eval/rpc动态改(重启即失效),仅适合临时排障:
/opt/accent-release/bin/accent rpc 'Logger.configure(level: :debug)'
对于生产,建议保持 :info:metadata 里已经带了 request_id,配合反向代理的 access log 足够定位请求;:debug 会把 Ecto 的 SQL 全量打出来,日志量与磁盘占用会明显上升。
11.2 DEBUG_ERRORS 的编译期陷阱(实测)
想在错误页看到堆栈,于是加 DEBUG_ERRORS=true,服务直接起不来:
ERROR! the application :accent has a different value set for path [:debug_errors]
inside key Accent.Endpoint during runtime compared to compile time. Since this
application environment entry was marked as compile time, this difference can
lead to different behavior than expected:
* Compile time value was set to: false
* Runtime value was set to: true
To fix this error, you might:
* Make the runtime value match the compile time one
* Recompile your project.
* Alternatively, you can disable this check...
Crash dump is being written to: erl_crash.dump...done
根因:config/prod.exs 已经把 debug_errors: false 写进编译期环境,runtime.exs 又用环境变量覆盖,OTP 的 validate_compile_env 直接拒绝启动。移除该变量后恢复正常:
[info] Running Accent.Endpoint with Bandit 1.13.0 at 0.0.0.0:8080 (http)
[info] Access Accent.Endpoint at http://localhost:8134
所以「调试错误页」不能在运行期开关,只能在构建时改 prod.exs 并重新打包。生产正确做法是保留 false,用 Sentry/日志排查。
十二、一份可直接用的生产配置清单
# ---- 必需 ----
PORT=4000
DATABASE_URL=postgresql://accent:q1w2e3r4@127.0.0.1:5432/accent_prod
SECRET_KEY_BASE=<openssl rand -hex 64>
SIGNING_SALT=<固定随机串,勿改>
MACHINE_TRANSLATIONS_VAULT_KEY=<固定随机串,勿改>
# ---- 站点 ----
CANONICAL_URL=https://translate.example.com
DISABLE_CANONICAL_HOST_REDIRECT=1
# 不要设置 FORCE_SSL(v1.32.1 不读取)
# ---- 数据库调优 ----
DATABASE_POOL_SIZE=20
DATABASE_TIMEOUT=29000
# ---- 邮件 ----
MAILER_FROM=accent@example.com
SMTP_ADDRESS=10.0.0.25
SMTP_PORT=587
SMTP_USERNAME=accent
SMTP_PASSWORD=<口令>
# ---- 登录 ----
# 生产不要设置 DUMMY_LOGIN_ENABLED(注意:设为 0/false 也会开启)
OIDC_CLIENT_ID=<client-id>
OIDC_CLIENT_SECRET=<client-secret>
OIDC_ISSUER=https://idp.example.com/realms/main
RESTRICTED_PROJECT_CREATOR_EMAIL_DOMAIN=example.com
# ---- 可选 ----
LANGUAGE_TOOL_LANGUAGES=zh,en
SENTRY_DSN=<dsn>
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
TZDATA_AUTOUPDATE_DISABLED=1
生效检查三步:
systemctl restart accent
systemctl is-active accent # active
journalctl -u accent -n 20 --no-pager | grep -E 'Running Accent|LanguageTool'
curl -s -o /dev/null -w '%{http_code}\n' https://translate.example.com/ # 200
十三、常见问题(排障实录)
Q1:变量加了 ACCENT_ 前缀,重启后毫无变化?
v1.32.1 不读任何 ACCENT_* 配置变量。去掉前缀,再用 bin/accent eval 打印实际配置值确认。
Q2:DUMMY_LOGIN_ENABLED=0 之后匿名登录还在?
该变量用 if get_env(...) 判空,"0" 是非空字符串,同样为真。必须删除变量本身。
Q3:改了 PORT,服务日志显示新端口,但外部仍访问不了?
服务端已生效(日志 at 0.0.0.0:8080),问题在端口转发/防火墙/反向代理 proxy_pass 未同步。逐层核对:ss -ltnp | grep 8080 → 安全组 → Nginx upstream。
Q4:配了 SMTP 却没收到邮件?
先看是否同时配了 SENDGRID_API_KEY(优先级更高,SMTP 被忽略);再看 MAILER_FROM 是否为空;最后确认没有落到 Bamboo.LocalAdapter(只写日志)。用 eval 打印 Accent.Mailer 一目了然。
Q5:邮件里的链接是 http://localhost:4000?
CANONICAL_URL 没配或配错。它同时决定邮件链接、OAuth 回调域名与 force_ssl,改了要重启。
Q6:反代之后一直 301 循环?
CANONICAL_URL 用了 https(自动开 SSL 重定向),而反代把 X-Forwarded-Proto 丢了,Accent 认为请求是 http 又重定向。补 proxy_set_header X-Forwarded-Proto $scheme;,并确认健康检查加 DISABLE_CANONICAL_HOST_REDIRECT=1。
Q7:改成 DEBUG_ERRORS=true 后服务起不来?
见 11.2,属编译期配置,运行期改必崩,删掉变量即可恢复。
Q8:机器翻译突然全部报密钥错误?
换过 MACHINE_TRANSLATIONS_VAULT_KEY。旧密文无法解密,需在项目设置里重新录入各服务密钥。
十四、参考链接
- Accent 源码
config/runtime.exs(v1.32.1):https://github.com/mirego/accent/blob/v1.32.1/config/runtime.exs - Accent 源码
lib/accent/config.ex:https://github.com/mirego/accent/blob/v1.32.1/lib/accent/config.ex - 角色权限定义
lib/accent/auth/role_abilities.ex:https://github.com/mirego/accent/blob/v1.32.1/lib/accent/auth/role_abilities.ex - Accent v1.32.1 介绍与选型指南:https://www.quzuo.net/document/Yj7L8j9xMed0
- Ubuntu 22.04 安装 Accent v1.32.1 指南:https://www.quzuo.net/document/4iSCcNNGGCAR