ejabberd 26.09 配置参数详解

ejabberd 26.09 配置逐节实测:dump_config/reload_config 查改闭环、宏环境变量覆盖、SQLite 切换对照、自签证书替换、ACL 增补管理员与生产模板,附单文件挂载排障实录。

ejabberd即时通信ejabberd2026/10/21

ejabberd 26.09 配置参数详解

目标:逐节讲透 ejabberd 26.09 主配置文件 ejabberd.yml 的核心参数——hosts、日志、证书与 ACME、监听器、s2s 联邦、认证、数据库、ACL 与访问规则、流控、模块——每节配真实修改动作与实测回显,并给出生产配置模板;全部操作在 Ubuntu 22.04.4 LTS 部署的 ejabberd 26.09 上实测通过。

一、环境信息

本章记录实测环境,正文所有命令与回显均出自该环境。

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64);
  • ejabberd:26.09(官方 ejabberd/ecs:26.09 部署,部署过程见 《Docker Compose 部署 ejabberd 指南》);
  • 配置文件:/srv/ejabberd/conf/ejabberd.yml(宿主)→ 容器内 /opt/ejabberd/conf/ejabberd.yml(即 /home/ejabberd/conf/ejabberd.yml,两路径同一文件),共 339 行,含完整官方注释;
  • 管理账号:admin@localhost / q1w2e3r4,另实测增补 ops@localhost;
  • 配置目录同时含:ejabberdctl.cfg(ejabberdctl 脚本行为)、server.pem(TLS 证书)、cacert.pem(CA 信任库)、dhparams.pem(DH 参数)、inetrc(DNS 解析配置)。

二、前置条件

按 《Docker Compose 部署 ejabberd 指南》第四章完成部署并确认服务在跑;本文配置目录以整目录方式挂载(./conf:/opt/ejabberd/conf:ro),管理员账号可正常登录 WebAdmin:

docker exec ejabberd-26.09-main ejabberdctl status

实测回显:

The node ejabberd@localhost is started with status: started
ejabberd 26.9.0 is running in that node

⚠️ 注意:若你的部署把配置文件以单文件方式挂载(./conf/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro),宿主上用 sed -i/vim 等「替换文件」的编辑器改配置后,容器内读到的仍是旧 inode 的内容——这是单文件 bind mount 的经典陷阱,实测踩中过(详见第七章 FAQ Q1)。本文所有实测基于整目录挂载,推荐读者也用整目录挂载。

三、参数查看与修改方式

改参数之前先解决两个问题:怎么看到「当前真正生效」的配置;改完后怎么让新配置生效。本章四种手段全部实测。

3.1 查看:dump_config 导出运行时配置

ejabberdctl dump_config <输出文件> 把 ejabberd 眼中实际生效的完整配置导出为 YAML——所有宏已展开、所有默认值已填充,是排查「我改的配置为什么没生效」的第一工具:

docker exec ejabberd-26.09-main ejabberdctl dump_config /opt/ejabberd/database/dump-live.yml
head -8 /srv/ejabberd/database/dump-live.yml

实测回显(输出节选):

hosts:
  - "localhost"
loglevel: info
certfiles:
  - /home/ejabberd/conf/server.pem
ca_file: "/home/ejabberd/conf/cacert.pem"
listen:
  -
    port: 5222

对比源文件与导出文件可见:源文件里 listen 段写的是宏 PORT_C2S,导出文件里已展开为 5222——宏机制只存在于源文件层,运行时全部落地为实值。

3.2 修改与热重载:reload_config

ejabberdctl reload_config 重读配置文件并应用,多数参数热生效无需重启。实测闭环:把日志级别从 info 改为 warning,热重载后用 dump_config 确认:

sed -i 's/^loglevel: info/loglevel: warning/' /srv/ejabberd/conf/ejabberd.yml
docker exec ejabberd-26.09-main ejabberdctl reload_config
docker exec ejabberd-26.09-main ejabberdctl dump_config /opt/ejabberd/database/dump-check.yml
grep '^loglevel' /srv/ejabberd/database/dump-check.yml

实测回显:

loglevel: warning

⚠️ 实测注意:并非所有参数都能热重载。实测 loglevel、acl、access_rules、modules、SQL 数据库参数均可热生效;certfiles 的文件清单变更实测未随 reload 生效(证书内容变更可热重载),需要重启服务:

docker compose restart ejabberd

3.3 环境变量宏覆盖:EJABBERD_MACRO_*

自 24.12 起,ejabberd 启动时读取 EJABBERD_MACRO_<名字> 环境变量,覆盖 define_macro 中同名宏。实测:给服务注入 EJABBERD_MACRO_HOST=chat.example.org 后重启,导出配置确认:

    environment:
      - EJABBERD_MACRO_HOST=chat.example.org
docker compose up -d --force-recreate
docker exec ejabberd-26.09-main ejabberdctl dump_config /opt/ejabberd/database/dump-macro.yml
grep -A2 '^hosts' /srv/ejabberd/database/dump-macro.yml

实测回显:

hosts:
  - "chat.example.org"

源文件 define_macro 里 HOST: localhost 未动,环境变量把它覆盖成 chat.example.org。这套机制让「同一份配置文件 + 不同环境变量」服务多套环境(测试/生产)成为可能。实测完成后移除该变量并重建,恢复 localhost 域。

3.4 修改生效方式对比

方式命令生效参数范围会话影响
热重载ejabberdctl reload_config多数运行参数(日志/ACL/模块/数据库)在线会话不断开
重启服务docker compose restart ejabberd全部(含 certfiles 清单)在线会话断开重连
重建服务docker compose up -d --force-recreate全部 + 挂载/环境变量变更同上,且重建工作负载
模块级重启ejabberdctl restart_module <域名> <模块>单个模块仅该模块功能短暂中断

选型建议:日常调参先 reload_config,验证手段统一用 dump_config 看运行时值;改监听端口、证书清单、环境变量这类「启动期参数」才走重启。

四、参数总览

一份 ejabberd.yml 的结构地图如下,按「全局 → 监听 → 存储与认证 → 权限 → 模块」五层组织:

配置段层级作用默认值(ecs 26.09)
define_macro全局定义宏变量,全文引用HOST=localhost、ADMIN=admin@localhost、各端口宏
hosts全局本服务器服务的 XMPP 域名列表- HOST(即 localhost)
loglevel全局日志级别info
certfiles / ca_file全局TLS 证书与 CA 信任库/home/ejabberd/conf/server.pem、cacert.pem
acme全局Let's Encrypt 自动证书staging CA + mailto 占位
listen监听各协议监听器5222/5223(c2s)、5269(s2s)、5280/5443/1880(http)、5478(stun)、1883(mqtt)、7777(proxy65)
s2s_use_starttls监听服务器联邦 TLS 策略optional
auth_method认证认证后端internal(默认,Mnesia 内置)
default_db / sql_*存储持久化后端Mnesia(不写即默认)
acl权限访问主体分组local/loopback/admin 三组
access_rules权限把 ACL 组映射到具体权限local/c2s/announce/configure 等
api_permissions权限管理命令的调用方授权console/webadmin/adhoc/http/public 五条
shaper / shaper_rules权限流量整形normal=3000B/s、fast=100000B/s
modules模块功能模块启停与参数40+ 个模块

💡 说明:define_macro 宏不是普通 YAML 语法而是 ejabberd 扩展,解析发生在 YAML 之前;宏让「域名、端口、管理员」这类跨段复用的值改一处即全局生效。

五、核心参数分类详解

以下每节都遵循「参数含义 → 实际修改动作 → 实测回显 → 要点」的闭环。修改动作均在实测环境真实执行。

5.1 hosts:服务域名

hosts 声明本服务器对外服务的 XMPP 域(用户 JID 的 @ 后缀),是最基础的参数:

hosts:
  - HOST

生产改法(假设域名 chat.example.com):

define_macro:
  HOST: chat.example.com
  ADMIN: "admin@chat.example.com"

hosts:
  - HOST

要点:改 HOST 必须同步改 ADMIN 宏(管理员 JID 含域);已有账号绑定旧域,改域后需重新注册或用迁移命令(ejabberdctl help accounts 中的账号命令均带域参数)。ecs 默认配置用宏引用而非硬编码域名,就是为了把这类联动收敛到宏定义一处。

5.2 loglevel:日志级别

顶层 loglevel 控制 ejabberd.log 的详细度,实测验证过 info ↔ warning 双向热切换(3.2 节闭环)。可选级别与取舍:

级别内容适用
debug协议包级明细,日志量巨大深度排障,短期
info启动、会话、模块事件默认,生产可用
warning仅告警与错误长期稳定运行降噪

日志文件位置:/opt/ejabberd/logs/(挂载到宿主 /srv/ejabberd/logs/),默认两类——ejabberd.log(主日志)与 error.log(错误),外加 crash.log(崩溃转储,按需出现)。日志轮转参数(log_rotate_size/log_rotate_count/log_rotate_date)默认按日期轮转,大流量场景建议显式设 log_rotate_size。

5.3 certfiles 与 ACME:TLS 证书

certfiles 是证书文件路径列表,支持通配,ejabberd 按「证书 SAN 与域名匹配」自动分发到各监听器:

certfiles:
  - /home/ejabberd/conf/server.pem
ca_file: "/home/ejabberd/conf/cacert.pem"

实测一:换成自签证书。 生成包含 localhost 与会议子域 SAN 的自签证书,改 certfiles 指向后重启:

openssl req -x509 -newkey rsa:2048 -keyout ejabberd.key -out server2.pem -days 365 -nodes \
  -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost,DNS:conference.localhost'
cat ejabberd.key >> server2.pem
# certfiles 指向 server2.pem 后重启
docker compose restart ejabberd

验证实际下发的证书(XMPP STARTTLS 握手):

echo QUIT | timeout 8 openssl s_client -connect 127.0.0.1:5222 -starttls xmpp -xmpphost localhost 2>&1 | grep -E 'subject|Verification'

实测回显(替换前):

subject=C = FR, ST = Paris, L = Paris, O = ProcessOne, OU = IT, CN = localhost
Verification error: self-signed certificate

实测回显(替换后):

subject=CN = localhost
Verification error: self-signed certificate

subject 从镜像自带证书的 O = ProcessOne 组织字段变为新证书仅有的 CN = localhost,确认 certfiles 切换生效。

实测二:ACME 自动证书。 默认配置自带 ACME 段(指向 Let's Encrypt staging 测试环境):

acme:
   contact: "mailto:example-admin@example.com"
   ca_url: "https://acme-staging-v02.api.letsencrypt.org/directory"

生产启用三步:① contact 改为真实邮箱;② ca_url 改为正式环境 https://acme-v02.api.letsencrypt.org/directory;③ 确保服务器 80/443 可达公网(ACME HTTP-01 验证)。配套管理命令实测可用:

docker exec ejabberd-26.09-main ejabberdctl help acme

实测回显(输出节选):

  acme
     list_certificates request_certificate revoke_certificate

⚠️ 注意:内网或无公网 80 端口的部署用不了 ACME HTTP-01,走自签 + 客户端信任或购买证书即可;list_certificates 在未启用 ACME 时输出为空属正常。

5.4 listen:监听器全家桶

listen 是端口矩阵,每项一个监听器。ecs 默认配置的完整清单(已实测在容器内监听):

端口module用途关键参数
5222ejabberd_c2s客户端明文口(STARTTLS)starttls_required: true 强制升级加密
5223ejabberd_c2s客户端直连 TLS 口tls: true
5269ejabberd_s2s_in服务器联邦入口max_stanza_size: 524288
5280ejabberd_httpWebAdmin(HTTP)request_handlers /admin
5443ejabberd_httpTLS 综合口/admin /api /bosh /captcha /upload /oauth /websocket 七个处理器
1880ejabberd_http管理台根路径(桌面环境友好)request_handlers /
5478/UDPejabberd_stunSTUN/TURN(音视频打洞)use_turn + 端口区间 50000-50099
1883mod_mqttMQTT 接入backlog 1000
7777mod_proxy65SOCKS5 文件传输代理access: local

三个最高频的改动:

① 关闭不用的口(最小暴露面,如禁联邦)——直接删除 5269 监听器段并重启;

② 调整客户端口的 TLS 策略——starttls_required: STARTTLS_REQUIRED 宏展开为布尔 true,生产保持强制:

  -
    port: PORT_C2S
    ip: "::"
    module: ejabberd_c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    starttls_required: STARTTLS_REQUIRED

逐项说明:ip: "::" 双栈监听;max_stanza_size 单个 XML stanza 上限(262144 字节,防超大包攻击);shaper 绑定流量整形规则(见 5.10);access 绑定访问规则名(见 5.8)。

③ 加 REST API 口(运维自动化用)——在 5443 的 request_handlers 里已有 /api: mod_http_api,若要在 5280 明文口也开 API,加一行 /api: mod_http_api 并重启。

5.5 s2s:服务器联邦参数

联邦(与其他 XMPP 域互通)相关参数集中在 s2s_* 前缀,默认配置启用一组关键项:

s2s_use_starttls: optional

实测环境下的联邦开关组合:

参数取值含义
s2s_use_starttlsoptional / required / false联邦 TLS:可选升级 / 强制 / 关闭
s2s_access规则名联邦访问控制(默认 all 放行)
s2s_timeout毫秒联邦连接超时

⚠️ 注意:关闭联邦不只是删 5269 监听器,还应设置 s2s_access 拒绝出站,两者配合才完整。内网私有部署建议 s2s_use_starttls: required 且仅在确需跨域时开放 5269。

5.6 认证:auth_method

auth_method 指定账号验证后端,默认 internal(账号存本库,register 命令写入)。可选后端一览:

💡 技术拓展:认证后端不止内置一种,常见选项对比——

后端写法适用场景
internal(默认)不配置或 auth_method: internal独立部署,账号自管
sqlauth_method: sql + default_db/sql_*账号存 MySQL/PG/SQLite
ldapauth_method: ldap + ldap_* 段对接企业 AD/OpenLDAP,只读验证
anonymousauth_method: anonymous免注册临时会话(访客场景)
jwtauth_method: jwt + jwt_key外部系统签发令牌直登

本文部署为独立内网环境,采用默认 internal;企业已有 AD/LDAP 时优先 ldap 免去账号双写。

多后端可共存(列表形式),ejabberd 按序尝试。改认证后端后 register/check_password 行为随之后端变化——实测 LDAP 后端时 register 会拒绝写账号(LDAP 只读),这是验证后端切换是否生效的快速手段。

5.7 数据库:default_db 与 sql_*(实测切换)

默认全部数据存 Mnesia(零依赖)。切到 SQL 后端的核心三参数(实测以 SQLite 验证,MySQL/PostgreSQL 写法同类):

default_db: sql
sql_type: sqlite
sql_database: /opt/ejabberd/database/ejabberd-sqlite.db

实测全程记录:在运行中的服务追加以上三行 → reload_config 热切换 → 日志出现建库过程:

2026-10-21 09:00:20.584 [info] Storing sqlite database for host localhost in file /opt/ejabberd/database/ejabberd-sqlite.db
2026-10-21 09:00:20.585 [error] SQL query 'select version from schema_version where module='ejabberd_auth_sql'' failed: ~c"no such table: schema_version"
2026-10-21 09:00:20.587 [info] Creating :sqlite table schema_version

首查 schema_version 报 no such table 是首次建库的正常路径(先查版本表不存在→创建),紧随其后自动建齐全部表。此时验证账号视角的隔离效果:

docker exec ejabberd-26.09-main ejabberdctl register tester localhost test123456
docker exec ejabberd-26.09-main ejabberdctl registered_users localhost

实测回显(SQLite 后端下):

User tester@localhost successfully registered
tester

新注册的 tester 落在 SQLite;切回 Mnesia(删除三行配置再 reload_config)后:

docker exec ejabberd-26.09-main ejabberdctl registered_users localhost

实测回显:

admin

原 Mnesia 库的 admin 原样还在,SQLite 库里的 tester 也不丢——两套后端数据完全独立,切换不是迁移。要把旧数据搬过去用 ejabberdctl export_db(导出 SQL)后再导入。

生产建议(写明场景):default_db: sql + PostgreSQL 适合「万级用户以上、MAM 消息存档长期保留」的主机(官方在默认配置 mod_mam 注释中也明确建议 SQL 后端——Mnesia 有 2GB 上限且易损);SQLite 适合小型独立部署;MySQL 折中。sql_server/sql_database/sql_username/sql_password 四参数用于外部数据库连接。

5.8 acl 与 access_rules:权限双件套

acl 定义「主体集合」,access_rules 把集合映射到权限,两层解耦。默认配置:

acl:
  local:
    user_regexp: ""
  loopback:
    ip:
      - 127.0.0.0/8
      - ::1/128
  admin:
    user:
      - ADMIN

access_rules:
  local:
    allow: local
  c2s:
    deny: blocked
    allow: all
  announce:
    allow: admin
  configure:
    allow: admin
  muc_create:
    allow: local
  pubsub_createnode:
    allow: local
  trusted_network:
    allow: loopback

逐项说明:acl.local 正则匹配所有本域注册用户;acl.loopback 限回环地址;acl.admin 引用 ADMIN 宏。access_rules 里 configure(管理台改配置)、announce(全站广播)只给 admin;muc_create 允许本域用户建群聊房;trusted_network 只含回环——这就是默认配置下 mod_register 的 ip_access: trusted_network 只允许本机自助注册的原因。

实测:增补第二个管理员。 在 acl.admin 追加 ops@localhost 并热重载:

  admin:
    user:
      - ADMIN
      - ops@localhost
docker exec ejabberd-26.09-main ejabberdctl register ops localhost q1w2e3r4
curl -s -o /dev/null -w '%{http_code}\n' -u 'ops@localhost:q1w2e3r4' http://127.0.0.1:8143/admin/server/localhost/

实测回显:

User ops@localhost successfully registered
200

ops 账号注册即获得 WebAdmin 服务器管理页访问权(HTTP 200),全程无需重启。ACL 主体写法速查:user:(单个 JID)、user_regexp:(正则)、ip:(网段)、all(内置,人人)。

5.9 api_permissions:管理命令授权

ejabberd 的每个管理命令(ejabberdctl/WebAdmin/REST API 共用同一命令池)由 api_permissions 决定「谁能从哪个通道调什么」:

api_permissions:
  "console commands":
    from: ejabberd_ctl
    who: all
    what: "*"
  "webadmin commands":
    from: ejabberd_web_admin
    who: admin
    what: "*"
  "http access":
    from: mod_http_api
    who:
      access:
        allow:
          - acl: loopback
          - acl: admin
      oauth:
        scope: "ejabberd:admin"
        access:
          allow:
            - acl: loopback
            - acl: admin
    what:
      - "*"
      - "!stop"
      - "!start"
  "public commands":
    who:
      ip: 127.0.0.1/8
    what:
      - status
      - connected_users_number

逐项说明:本机 ejabberdctl 全放行(console commands);WebAdmin 仅 admin 组;REST API(http access)仅回环与 admin 组可调,且显式排除 stop/start(! 前缀即排除);public commands 允许本机匿名查状态。给自动化系统开 API 时,照 http access 的模式加 ACL 限定来源 IP,并按需收紧 what 清单——这是官方默认就示范的最佳实践。

5.10 shaper:流量整形

shaper 定义速率(字节/秒),shaper_rules 决定谁套哪种速率:

shaper:
  normal:
    rate: 3000
    burst_size: 20000
  fast: 100000

shaper_rules:
  max_user_sessions: 10
  max_user_offline_messages:
    5000: admin
    100: all
  c2s_shaper:
    none: admin
    normal: all
  s2s_shaper: fast

逐项说明:normal 限 3000 字节/秒、允许 20000 字节突发;c2s_shaper 规则「管理员不限速、普通用户走 normal」;max_user_sessions: 10 单账号最多 10 并发会话(多端登录上限);max_user_offline_messages 离线消息上限按身份分档(admin 5000 条、普通 100 条)。文件传输类流量(proxy65)走 fast 档。高并发消息推送场景把 rate 上调或给推送账号建专用 ACL 走 none。

5.11 modules:模块启停

modules 段列启用模块,ecs 默认启用 40+ 个。三类典型改法:

modules:
  mod_adhoc: {}
  mod_mam:
    db_type: sql
    assume_mam_usage: true
    default: always
  mod_muc:
    access:
      - allow
    access_admin:
      - allow: admin
    access_create: muc_create
    default_room_options:
      mam: true
  mod_register:
    ip_access: trusted_network
  mod_version:
    show_os: false

逐项说明:空映射 {} 表示全默认;mod_mam 的 db_type: sql 单独指定消息存档走 SQL(官方注释建议——Mnesia 有 2GB 上限);default: always 默认为所有会话存档;mod_muc 的 access_create: muc_create 把建房权交给 5.8 定义的规则;mod_register.ip_access: trusted_network 收紧自助注册来源;mod_version.show_os: false 不泄露操作系统版本(安全加分项)。

模块的在线装卸(不占 modules 段的 contrib 社区模块):

docker exec ejabberd-26.09-main ejabberdctl modules_available | head -5
docker exec ejabberd-26.09-main ejabberdctl module_install <模块名>

六、生产配置模板

适用场景:8GB 内存 / SSD 磁盘 / 千人级企业内部 IM,账号对接外部 PostgreSQL,开启联邦。在默认配置基础上聚焦差异项:

define_macro:
  HOST: chat.example.com
  ADMIN: "admin@chat.example.com"
  STARTTLS_REQUIRED: true

hosts:
  - HOST

loglevel: warning

certfiles:
  - "/etc/letsencrypt/live/chat.example.com/fullchain.pem"
  - "/etc/letsencrypt/live/chat.example.com/privkey.pem"

acme:
  contact: "mailto:it-admin@example.com"
  ca_url: "https://acme-v02.api.letsencrypt.org/directory"

default_db: sql
sql_type: pgsql
sql_server: "10.0.0.8"
sql_database: "ejabberd"
sql_username: "ejabberd"
sql_password: "从内部密钥管理下发的强口令"

s2s_use_starttls: required

shaper_rules:
  max_user_sessions: 20
  c2s_shaper:
    none: admin
    normal: all

modules:
  mod_mam:
    db_type: sql
    default: always
  mod_muc:
    access_create: muc_create
    default_room_options:
      mam: true
  mod_register:
    ip_access: trusted_network
  mod_fail2ban: {}
  mod_version:
    show_os: false

模板要点:域名/管理员收敛进宏;日志降噪 warning;证书指向 ACME 正式目录(ACME 段留作自动续期);数据与 MAM 全走外部 PostgreSQL(8GB 内存主机给 PostgreSQL 分 2GB 足够千人级);联邦强制 TLS;登录口令必须换掉演示值——生产口令经密钥管理下发,不落明文。

七、常见问题(FAQ)

Q1:宿主改了 ejabberd.yml,容器里 reload_config 后还是旧行为?

实测现象:宿主 sed -i 修改配置、执行 reload_config,dump_config 看到的仍是旧值。定位:部署用了单文件 bind mount,sed -i/vim 以「写临时文件再改名」方式保存,文件 inode 变了,容器挂载仍指向旧 inode(实测宿主 inode 9191669 vs 容器内 9191601)。解决:改用整目录挂载(./conf:/opt/ejabberd/conf:ro)后重建服务;目录挂载下文件替换对容器立即可见。顺带提醒:不要用 sed ... | tee 同一文件 的管道就地改——读写同一文件并发会把文件清空(实测踩中,文件变 0 字节),先写临时文件再 mv。

Q2:reload_config 后 certfiles 的新文件路径不生效?

实测确认:certfiles 清单变更需要重启(docker compose restart ejabberd)才加载新路径;已有路径下的证书内容更新可以热重载。判定技巧:证书替换后用 openssl s_client 看 subject 是否变化(5.3 节实测手法)。

Q3:切 SQL 后 registered_users 变空了,数据丢了吗?

没丢。5.7 节实测证明 Mnesia 与 SQL 是两套独立存储,切换视角后各自可见各自账号。找回旧数据:切回 default_db 原值即见原账号;正式迁移用 ejabberdctl export_db。

Q4:SQLite 首次切换时日志报 no such table: schema_version 错误?

首次建库的正常现象:ejabberd 先查 schema 版本表→不存在→自动创建全部表结构(5.7 节回显完整记录了这条路径)。后续重启不再出现;若反复出现且表建不出来,检查 sql_database 路径目录属主是否为容器内 ejabberd 账号(UID 9000)。

Q5:改了宏但好像没生效?

按优先级排查:环境变量 EJABBERD_MACRO_* 覆盖配置文件 define_macro(3.3 节实测 hosts 被 env 覆盖为 chat.example.org);宏名大小写敏感;宏定义必须在引用之前。最终以 dump_config 导出值为准——它反映宏展开后的运行时真相。

八、参考链接

  1. 官方配置文档总览:https://docs.ejabberd.im/admin/configuration/
  2. 官方文件格式与宏说明:https://docs.ejabberd.im/admin/configuration/file-format/
  3. 官方数据库配置文档:https://docs.ejabberd.im/admin/configuration/database/
  4. 官方 ACME 配置文档:https://docs.ejabberd.im/admin/configuration/basic/#acme
  5. 官方监听器文档:https://docs.ejabberd.im/admin/configuration/listen/
  6. 官方 acl/access 文档:https://docs.ejabberd.im/admin/configuration/access/
  7. 官方模块文档:https://docs.ejabberd.im/admin/configuration/modules/
  8. 同系列部署篇:《Docker Compose 部署 ejabberd 指南》
  9. 同系列命令篇:《ejabberd 常用 CLI 命令详解》
  10. 版本来源:https://github.com/processone/ejabberd/releases.atom(26.09,查询日期 2026-10-21)