Azimutt 2.0 配置参数详解
以服务器视角逐项详解 Azimutt 2.0 环境变量:runtime.exs 的 fetch_env!/布尔开关/默认值三类读取机制与实测装配痕迹,必需五项、网络/数据库/认证/邮件/存储/平台开关/可观测集成各族参数映射与生效证据,附生产 env 模板与启动失败排障。
Azimutt 2.0 配置参数详解
目标:以服务器视角(安装目录
/opt/azimutt/app,Erlang release 形态)逐项讲清 Azimutt 2.0 的全部环境变量:config/runtime.exs的读取与映射机制、必需项与认证/网络/邮件/存储/可观测/平台开关各族参数、实测生效证据与生产配置模板。
一、环境信息
- 组件版本:Azimutt 2.0(release 构建号
2.0.1787693602,OTP 25 / Elixir 1.14.3 / ERTS 13.1.4) - 安装目录:
/opt/azimutt/app,release 标准布局(实测ls /opt/azimutt/app):
app
bin
erts-13.1.4
lib
releases
- 配置注入:进程启动时读取的环境变量(本文以 env 文件
/opt/azimutt/app.env为口径,经启动器 source 注入) - 元数据库:PostgreSQL 16(
DATABASE_URL指向);数据面 gateway@azimutt/gateway0.1.26 独立进程、独立环境变量(拓扑见 《Azimutt Docker Compose 部署指南》) - 验证入口:
http://192.168.1.200:8136(应用)、http://192.168.1.200:8137(gateway) - 参数事实源:官方
config/runtime.exs(本文代码片段引自 2026-11-03 拉取的main构建源码)与官方 INSTALL.md 环境变量表;生效证据均为本环境实测
二、前置准备
- 已完成 Azimutt 部署(流程见 《Azimutt Docker Compose 部署指南》);
- 具备应用安装目录读写权限与重启应用能力(
/opt/azimutt/app/bin/azimutt restart); - 准备一个 ≥64 字节随机密钥:
$ openssl rand -hex 32
cd0ba5b8f7f85b8b0a140a25af22106b5aebf37cc39206a67559877eeb649afb
三、参数查看与修改方式
3.1 配置形态:纯环境变量
Azimutt 没有可编辑的运行时配置文件——config/runtime.exs 在每次进程启动时从环境变量装配配置。当前生效值直接看 env 文件:
$ cat /opt/azimutt/app.env
PHX_SERVER=true
PHX_PROTOCOL=ipv4
PHX_HOST=localhost
PORT=4000
SECRET_KEY_BASE=08383932639413583b2343a17290e77c8dca6026d3abc6a032fbb09e0be930c3183a1b7142bbfdf5
DATABASE_URL=postgresql://postgres:q1w2e3r4@192.168.1.200:5432/azimutt
DATABASE_POOL_SIZE=10
GATEWAY_URL=http://192.168.1.200:8137
FILE_STORAGE_ADAPTER=local
AUTH_PASSWORD=true
SKIP_ONBOARDING_FUNNEL=true
SKIP_EMAIL_CONFIRMATION=true
PUBLIC_SITE=false
3.2 读取机制:runtime.exs 的三类取值函数
源码里的三个小函数决定了所有参数的容错行为(config/runtime.exs 第 4~6 行):
fetch_env! = fn key ->
case System.get_env(key) do
nil -> raise "environment variable #{key} is missing"
"" -> raise "environment variable #{key} is blank"
value -> value
end
end
- 必需项用
fetch_env!:缺失或空字符串都会在启动时直接 raise(见 7.1/7.2); - 布尔开关用
System.get_env("X") == "true":只有字面true算开,其余(含1、yes)都是关; - 可选项用
|| 默认值兜底(如DATABASE_POOL_SIZE默认10)。
每次装配都会打印运行痕迹(实测执行任何 release 命令都会先输出):
Setup Local file storage
Setup Local email provider
Setup Password auth
这三行分别对应 FILE_STORAGE_ADAPTER=local、未设 EMAIL_ADAPTER(落到 Local provider)、AUTH_PASSWORD=true 的装配结果,是核对「开关是否真的生效」最快的探针。
3.3 修改与生效
改 env 文件后重启应用进程即可(bin/azimutt restart 或由进程管理器重启)。注意:eval/rpc 等命令也会重新走一遍 runtime.exs 装配(3.2 的 Setup 行在 eval 时同样打印),但不会改变正在运行实例的行为。
四、参数总览
| 分组 | 变量 | 必需性 | 默认值 | 作用 |
|---|---|---|---|---|
| 必需 | SECRET_KEY_BASE | 必需 | 无 | 会话/cookie 加密密钥,≥64 字节随机值 |
| 必需 | DATABASE_URL | 必需 | 无 | 元数据库连接串 |
| 必需 | PHX_HOST | 必需 | 无 | 构建绝对 URL 的 host |
| 必需 | PORT | 必需 | 无 | 监听端口 |
| 必需 | FILE_STORAGE_ADAPTER | 必需 | 无 | 文件存储驱动:local/s3 |
| 网络 | PHX_SERVER | 可选 | 关 | true 才以服务器模式监听端口 |
| 网络 | PHX_PROTOCOL | 可选 | ipv6 | ipv4 时监听 0.0.0.0 |
| 网络 | GATEWAY_URL | 可选 | 无 | 注入前端 window.gateway_url |
| 数据库 | DATABASE_POOL_SIZE | 可选 | 10 | 连接池大小 |
| 数据库 | DATABASE_IPV6 | 可选 | 关 | 驱动走 IPv6 |
| 数据库 | DATABASE_ENABLE_SSL | 可选 | 关 | 连元数据库启用 SSL |
| 认证 | AUTH_PASSWORD | 可选 | 关 | 邮箱+密码认证 |
| 认证 | AUTH_GITHUB | 可选 | 关 | GitHub SSO(需 client id/secret) |
| 认证 | AUTH_GOOGLE/LINKEDIN/TWITTER/FACEBOOK/SAML | 可选 | 关 | 设 true 会启动报错(未实现) |
| 邮件 | EMAIL_ADAPTER | 可选 | Local | mailgun/gmail/smtp/none |
| 邮件 | SENDER_EMAIL 等 4 项 | 可选 | contact@azimutt.app | 发件/联系/支持邮箱 |
| 存储 | S3_BUCKET 等 6 项 | s3 时必需 | 见 5.6 | 对象存储参数 |
| 开关 | PUBLIC_SITE | 可选 | 关 | true 展示官网页 |
| 开关 | SKIP_ONBOARDING_FUNNEL | 可选 | 关 | 跳过新用户引导 |
| 开关 | SKIP_EMAIL_CONFIRMATION / REQUIRE_EMAIL_CONFIRMATION | 可选 | 关 | 邮箱验证软硬开关 |
| 开关 | REQUIRE_EMAIL_ENDS_WITH | 可选 | 无 | 强制邮箱后缀 |
| 开关 | ORGANIZATION_DEFAULT_PLAN | 可选 | free | 新组织默认套餐 |
| 开关 | GLOBAL_ORGANIZATION(_ALONE) | 可选 | 无 | 全局组织/单租户模式 |
| 开关 | LICENCE_KEY | 可选 | 无 | 付费功能解锁 |
| 可观测 | SENTRY + SENTRY_BACKEND_DSN/SENTRY_FRONTEND_DSN | 可选 | 关 | 错误上报 |
| 可观测 | RECAPTCHA + 3 项 | 可选 | 关 | 注册/登录人机验证 |
| 集成 | STRIPE/HEROKU/CLEVER_CLOUD/POSTHOG/BENTO/HUBSPOT/GITHUB/TWITTER | 可选 | 关 | 平台/分析集成开关族 |
五、核心参数分类详解
5.1 必需五项(缺失即启动失败)
database_url = fetch_env!.(%{"DATABASE_URL" => url})
# (节选,下同)
secret = fetch_env!.(%{"SECRET_KEY_BASE" => secret})
host = fetch_env!.(%{"PHX_HOST" => host})
port = String.to_integer(fetch_env!.(%{"PORT" => port}))
SECRET_KEY_BASE:Phoenix 会话签名根密钥,fetch_env!语义下空串同样 raise;DATABASE_URL:元数据库(账号/组织/项目/注释)连接串,形如postgresql://<user>:<pass>@<host>:<port>/<database>;PHX_HOST+PORT:拼进 Endpoint 的绝对 URL(host: host, port: port, publish: port,scheme 固定https、force_ssl默认开启,见 5.2);FILE_STORAGE_ADAPTER:只接受local/s3,其他值直接raise "unknown FILE_STORAGE_ADAPTER"。
实测本环境五项取值见 3.1;bin/azimutt version 核对应用版本:
azimutt 2.0.1787693602
5.2 网络与端点族
config :azimutt, Azimutt.Mailer, adapter: mailer_adapter
config :phoenix, :serve_endpoints, System.get_env("PHX_SERVER") == "true"
# PHX_PROTOCOL: ipv4 时 listen_address = {0, 0, 0, 0},否则 {0, 0, 0, 0, 0, 0, 0, 1}
| 变量 | 取值 | 实测效果 |
|---|---|---|
PHX_SERVER | true | 不监听端口 → 设 true 后日志出现 Running AzimuttWeb.Endpoint with cowboy 2.12.0 at 0.0.0.0:4000 (http) |
PHX_PROTOCOL | ipv4 | 默认 ipv6(监听 ::),IPv4-only 宿主网络下必须显式改 ipv4(监听 0.0.0.0) |
PHX_HOST | localhost | 日志 Access AzimuttWeb.Endpoint at https://localhost——绝对 URL 的 host 即此值(生产填域名) |
GATEWAY_URL | http://192.168.1.200:8137 | 注入项目页 window.gateway_url(实测见下) |
$ curl -s -H "Cookie: $SCK" http://192.168.1.200:8136/projects/4d40deb4-3df6-48d9-be54-76636daf6c65 | grep -o "window.gateway_url[^;]*" # $SCK 为登录后从响应头提取的 _azimutt_key 会话 cookie
window.gateway_url = 'http://192.168.1.200:8137'
GATEWAY_URL 的值由浏览器直连使用,必须是浏览器可达地址;留空则前端退回公共 gateway 或本地 CLI 方案。
5.3 数据库族
config :azimutt, Azimutt.Repo,
url: url,
pool_size: String.to_integer(System.get_env("DATABASE_POOL_SIZE") || "10"),
socket_opts: [inet6: System.get_env("DATABASE_IPV6") == "true"],
parameters: [application_name: "azimutt"],
ssl: System.get_env("DATABASE_ENABLE_SSL") == "true" && [verify: :verify_none]
DATABASE_POOL_SIZE:默认 10,本环境显式设10;元数据库连接数不大,4C8G 机器无需调高;DATABASE_ENABLE_SSL:true时verify_none(不校验证书链,内网自签场景够用);DATABASE_IPV6:元数据库在 IPv6-only 环境时开启。
5.4 认证族
| 变量 | 行为(源码语义) |
|---|---|
AUTH_PASSWORD=true | 装配 AuthPassword provider(启动日志 Setup Password auth);/register 可用 |
AUTH_GITHUB=true | 必需 GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET(fetch_env! 缺失即 raise) |
AUTH_GOOGLE/AUTH_LINKEDIN/AUTH_TWITTER/AUTH_FACEBOOK/AUTH_SAML | 设 true 一律 raise "AUTH_XXX is not implemented yet"——目前只有邮箱密码与 GitHub 两种可用 |
密码策略为组件内置校验:12~72 位。实测 8 位口令 q1w2e3r4 登录返回 200 且页面含:
<p class="alert alert-danger">Email or Password invalid.</p>
因此示例账号统一为 admin@azimutt.local / q1w2e3r4q1w2(12 位)。实测 AUTH_PASSWORD=true 的注册页状态码:
$ curl -s -o /dev/null -w 'register=%{http_code}\n' http://192.168.1.200:8136/register
register=200
5.5 邮件族
mailer_adapter =
case System.get_env("EMAIL_ADAPTER") do
nil -> Azimutt.Mailer.Local
"mailgun" -> Bamboo.MailgunAdapter
"gmail" -> Bamboo.GmailAdapter
"smtp" -> Bamboo.SMTPAdapter
"none" -> Swoosh.Adapters.Local
_ -> raise "unknown EMAIL_ADAPTER"
end
- 不设
EMAIL_ADAPTER→ 落Azimutt.Mailer.Local(启动日志Setup Local email provider,实测):邮件不外发,仅本地留存。自托管内网通常配合SKIP_EMAIL_CONFIRMATION=true使用; smtp需SMTP_RELAY/SMTP_USERNAME/SMTP_PASSWORD/SMTP_PORT;mailgun需MAILGUN_DOMAIN/MAILGUN_API_KEY/MAILGUN_BASE_URL;gmail需GMAIL_ACCESS_TOKEN;- 四个邮箱变量按「专用→回退」链取值:
SENDER_EMAIL(发件人,默认contact@azimutt.app)、CONTACT_EMAIL(页面展示联系邮箱)、SUPPORT_EMAIL(回退 CONTACT)、ENTERPRISE_SUPPORT_EMAIL(回退 SUPPORT)。
5.6 存储族
case fetch_env!.(%{"FILE_STORAGE_ADAPTER" => adapter}) do
"local" -> Azimutt.FileStorage.Local
"s3" -> Azimutt.FileStorage.S3
_ -> raise "unknown FILE_STORAGE_ADAPTER"
end
local:项目文件落应用目录bin/uploads(本环境即/opt/azimutt/app/bin/uploads,需持久化备份);s3:必需S3_BUCKET,可选S3_HOST/S3_KEY_ID/S3_KEY_SECRET/S3_FOLDER/S3_REGION(默认eu-west-1);- 注意:
storage_kind=local的项目 schema 存在浏览器端,服务端 uploads 为空属正常;remote项目才写文件存储。
5.7 平台开关与入驻流程族
| 变量 | 实测/源码效果 |
|---|---|
PUBLIC_SITE=false | 首页不再展示官网,直接重定向登录页(实测见下) |
SKIP_ONBOARDING_FUNNEL=true | 新用户不再走引导漏斗(内网部署建议开) |
SKIP_EMAIL_CONFIRMATION=true | 跳过邮箱验证(无邮件服务时必开) |
REQUIRE_EMAIL_CONFIRMATION=true | 未验证邮箱禁止使用(与 SKIP 互斥语义,二选一) |
REQUIRE_EMAIL_ENDS_WITH=@corp.example.com | 强制企业邮箱后缀注册 |
ORGANIZATION_DEFAULT_PLAN | 新组织默认套餐:free/solo/team/enterprise/pro |
GLOBAL_ORGANIZATION=<org-id> | 新用户自动加入指定组织;GLOBAL_ORGANIZATION_ALONE=true 只展示该组织(单租户形态) |
LICENCE_KEY | 解锁付费功能;fetch_env! 语义下设空串会启动失败 |
PUBLIC_SITE=false 的实测效果:
$ curl -s -o /dev/null -w 'root=%{http_code} redirect=%{redirect_url}\n' http://192.168.1.200:8136/
root=302 redirect=http://192.168.1.200:8136/login
健康检查端点与开关无关,始终可用(实测):
$ curl -s -o /dev/null -w 'health=%{http_code}\n' http://192.168.1.200:8136/health
health=200
5.8 可观测与集成族
SENTRY=true+SENTRY_BACKEND_DSN/SENTRY_FRONTEND_DSN:错误上报;SENTRY=true但 DSN 未设时按空串装配(源码|| "",不会 raise);RECAPTCHA=true+RECAPTCHA_SITE_KEY/RECAPTCHA_SECRET_KEY(必需)/RECAPTCHA_MIN_SCORE(0.0~1.0,默认 0.5):注册/登录人机验证;STRIPE=true时源码会校验STRIPE_SECRET_KEY必须sk_/rk_前缀、STRIPE_PUBLIC_KEY必须pk_前缀,否则 raise;HEROKU/CLEVER_CLOUD:平台探测开关(fetch_env!,设空串会 raise);POSTHOG/BENTO/HUBSPOT/GITHUB/TWITTER:分析与社交集成族,内网部署全部保持未设置即可。
六、生产配置模板
场景:单机 4C8G、内网团队 20 人、邮箱密码登录、无外发邮件服务。env 文件全文:
# —— 必需五项 ——
PHX_SERVER=true # 不设置则不监听端口
PHX_PROTOCOL=ipv4 # bridge/宿主网络必须 ipv4
PHX_HOST=azimutt.corp.example.com # 绝对 URL host,配 TLS 反代
PORT=4000
SECRET_KEY_BASE=cd0ba5b8f7f85b8b0a140a25af22106b5aebf37cc39206a67559877eeb649afb # openssl rand -hex 32 生成
DATABASE_URL=postgresql://azimutt:<强口令>@10.0.0.21:5432/azimutt
FILE_STORAGE_ADAPTER=local # 团队规模小,本地目录 + 定期备份即可
# —— 网络与数据面 ——
DATABASE_POOL_SIZE=10 # 默认值,无需调
GATEWAY_URL=https://azimutt-gw.corp.example.com # 浏览器可达!与 CORS_ALLOW_ORIGIN 同步
# —— 认证与入驻 ——
AUTH_PASSWORD=true
SKIP_ONBOARDING_FUNNEL=true
SKIP_EMAIL_CONFIRMATION=true # 无 SMTP 时必须
REQUIRE_EMAIL_ENDS_WITH=@corp.example.com
PUBLIC_SITE=false # 关官网页,/ 直跳 /login
# —— 邮件(有 SMTP 时替换 Local)——
# EMAIL_ADAPTER=smtp
# SMTP_RELAY=smtp.corp.example.com
# SMTP_USERNAME=azimutt
# SMTP_PASSWORD=<口令>
# SMTP_PORT=587
# SENDER_EMAIL=azimutt@corp.example.com
# —— 可观测 ——
# SENTRY=true
# SENTRY_BACKEND_DSN=<DSN>
配套要点:TLS 反向代理终结 https 后转发 PORT;PHX_HOST 与代理域名一致;gateway 的 CORS_ALLOW_ORIGIN 等于浏览器访问应用的 origin(拓扑与验证见部署篇 《Azimutt Docker Compose 部署指南》)。
七、常见问题
7.1 启动报 environment variable XXX is missing
必需五项(5.1)任一未注入即触发 fetch_env! raise。排查:确认启动器真的把 env 文件 source 进了进程环境,而不是只写了文件。
7.2 设了变量却报 environment variable XXX is blank
fetch_env! 对空字符串同样 raise。LICENCE_KEY=、HEROKU= 这类「设了但留空」的写法都会踩中;不需要的开关直接删行,别留空值。
7.3 FILE_STORAGE_ADAPTER 设成别的值
只认 local/s3,其他值 raise "unknown FILE_STORAGE_ADAPTER"(5.6 源码)。
7.4 开了 AUTH_GOOGLE 等第三方登录起不来
AUTH_GOOGLE/AUTH_LINKEDIN/AUTH_TWITTER/AUTH_FACEBOOK/AUTH_SAML 在源码里是占位实现,设 true 直接 raise not implemented yet(5.4)。当前可用认证只有邮箱密码与 GitHub。
7.5 纯 http 下登录后仍是未登录态
会话 cookie 带 Secure; SameSite=None,浏览器在 http 连接拒收。解法:上 TLS 反代并把绝对 URL 配成 https(PHX_HOST 域名 + 反代证书);排障期用 curl 手动拼 Cookie 头可绕过(实测登录 302 流程见部署篇 4.5)。
7.6 注册/改密提示口令无效
密码强制 12~72 位(5.4 实测)。8 位 q1w2e3r4 会被拒(页面回显 Email or Password invalid.),示例账号统一用 q1w2e3r4q1w2。
7.7 改了 env 但行为没变
runtime.exs 只在进程启动(及 eval/rpc 等命令执行)时读取:重启应用进程后,用启动日志的三行 Setup 装配痕迹(3.2)核对装配结果,再看对应端点行为(如 PUBLIC_SITE 看 / 状态码、GATEWAY_URL 看 window.gateway_url)。
八、参考链接
- 《Azimutt 介绍与选型指南》:定位与版本生态
- 《Azimutt Docker Compose 部署指南》:部署与拓扑验证
- 官方安装文档(环境变量全表):https://github.com/azimuttapp/azimutt/blob/main/INSTALL.md
- 源码
config/runtime.exs:https://github.com/azimuttapp/azimutt/blob/main/config/runtime.exs - Phoenix 运行时配置概念:https://hexdocs.pm/phoenix/runtime_configuration.html