Azimutt 2.0 配置参数详解

以服务器视角逐项详解 Azimutt 2.0 环境变量:runtime.exs 的 fetch_env!/布尔开关/默认值三类读取机制与实测装配痕迹,必需五项、网络/数据库/认证/邮件/存储/平台开关/可观测集成各族参数映射与生效证据,附生产 env 模板与启动失败排障。

AzimuttAzimutt配置参数详解配置管理PostgreSQLElixir2026/11/03

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/gateway 0.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可选ipv6ipv4 时监听 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可选Localmailgun/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_SERVERtrue不监听端口 → 设 true 后日志出现 Running AzimuttWeb.Endpoint with cowboy 2.12.0 at 0.0.0.0:4000 (http)
PHX_PROTOCOLipv4默认 ipv6(监听 ::),IPv4-only 宿主网络下必须显式改 ipv4(监听 0.0.0.0)
PHX_HOSTlocalhost日志 Access AzimuttWeb.Endpoint at https://localhost——绝对 URL 的 host 即此值(生产填域名)
GATEWAY_URLhttp://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 2.0 配置参数详解 - Quzuo