emqx部署
使用内置数据库存储
# 用户认证配置(使用内置数据库)
EMQX_AUTHENTICATION__1__BACKEND: built_in_database # 认证后端类型为内置数据库
EMQX_AUTHENTICATION__1__ENABLE: true # 启用认证
EMQX_AUTHENTICATION__1__MECHANISM: password_based # 认证机制为密码认证
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__NAME: sha256 # 密码哈希算法为SHA256
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__SALT_POSITION: prefix # 盐值位置为前缀
EMQX_AUTHENTICATION__1__USER_ID_TYPE: username # 用户ID类型为用户名
# ACL配置(使用内置数据库)
EMQX_AUTHORIZATION__NO_MATCH: deny # 未匹配时拒绝访问
EMQX_AUTHORIZATION__SOURCES__1__TYPE: built_in_database # 授权类型为内置数据库
EMQX_AUTHORIZATION__SOURCES__1__ENABLE: true # 启用授权持久化配置
# 持久会话配置
EMQX_DURABLE_SESSIONS__ENABLE: true # 启用持久会话
EMQX_DURABLE_SESSIONS__BATCH_SIZE: 100 # 批处理大小
EMQX_DURABLE_SESSIONS__IDLE_POLL_INTERVAL: "1s" # 空闲轮询间隔
EMQX_DURABLE_SESSIONS__HEARTBEAT_INTERVAL: "10s" # 心跳间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_INTERVAL: "20h" # 会话垃圾回收间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_BATCH_SIZE: 100 # 垃圾回收批处理大小
# 集群配置(持久会话要求使用singleton模式)
EMQX_CLUSTER__DISCOVERY_STRATEGY: singleton # 集群发现策略设置为单例模式ACL 规则说明
字段含义:
username : 用户名
action : 操作类型( publish 、 subscribe 、 all )
permission : 权限( allow 、 deny )
topic : 主题模式(支持通配符 + 和 # )
通配符规则:
+: 匹配单层主题(如 device/+/status 匹配 device/001/status )#: 匹配多层主题(如 sensor/# 匹配 sensor/temp/room1 )
⚠️ 重要规则
#必须是最后一个字符
device/+/temp ≠ device/sensor01/room1/temp+只匹配一层
✅ device/+/status
❌ device/sensor+/status
❌ device/sensor#通配符不能与其他字符混用
✅ device/+/status
❌ device/sensor+/status
❌ device/sensor#区分大小写
Device/sensor01 ≠ device/sensor01🔧 ACL 配置示例
// 复杂权限控制示例
db.mqtt_acl.insertMany([
// 设备只能发布自己的数据
{
"username": "device001",
"action": "publish",
"permission": "allow",
"topic": "device/device001/+"
},
// 设备可以订阅命令
{
"username": "device001",
"action": "subscribe",
"permission": "allow",
"topic": "command/device001/#"
},
// 禁止访问其他设备
{
"username": "device001",
"action": "all",
"permission": "deny",
"topic": "device/+/+"
},
// 数据收集器可以订阅所有传感器数据
{
"username": "data_collector",
"action": "subscribe",
"permission": "allow",
"topic": "sensor/+/data/#"
}
])📊 权限优先级
具体规则优先于通配符规则
deny 优先于 allow
后定义的规则优先级更高
🎯 常用 ACL 模式
设备专用主题:
{
"username": "device001",
"action": "all",
"permission": "allow",
"topic": "device/device001/#"
}只读传感器:
{
"username": "sensor01",
"action": "publish",
"permission": "allow",
"topic": "sensor/+/data"
}管理员权限:
// 超级用户不需要 ACL 规则,设置 is_superuser: true 即可
配置SSL
SSL配置尝试使用环境变量的方式没有实现出来,只能在emqx.conf里面填写
[root@iZwz9j7dbsko7t0h3sgas0Z emqx]# cat etc/emqx.conf
## Place read-only configurations in this file.
## To define configurations that can later be overridden through UI/API/CLI, add them to `etc/base.hocon`.
##
## Config precedence order:
## etc/base.hocon < cluster.hocon < emqx.conf < environment variables
##
## See https://www.emqx.io/docs/en/latest/configuration/configuration.html for more information.
## Configuration full example can be found in etc/examples
node {
name = "emqx@127.0.0.1"
cookie = "emqxsecretcookie"
data_dir = "data"
}
cluster {
name = emqxcl
discovery_strategy = manual
}
dashboard {
listeners {
http.bind = 18083
# https.bind = 18084
https {
ssl_options {
certfile = "${EMQX_ETC_DIR}/certs/mirayai.com.pem"
keyfile = "${EMQX_ETC_DIR}/certs/mirayai.com.key"
cacertfile = "${EMQX_ETC_DIR}/certs/DigiCertGlobalRootCA.crt.pem"
}
}
}
}
listeners.ssl.default {
bind = "0.0.0.0:8883"
max_connections = 1024000
ssl_options {
# PEM 格式的文件,包含一个或多个用于验证客户端证书的根 CA 证书
# 单向认证时,该文件内容可以为空
cacertfile = "${EMQX_ETC_DIR}/certs/DigiCertGlobalRootCA.crt.pem"
# PEM 格式的服务器证书,如果证书不是直接由根 CA 签发,那么中间 CA 的证书必须加在服务器证书的后面组成一个证书链
certfile = "${EMQX_ETC_DIR}/certs/mirayai.com.pem"
# PEM 格式的密钥文件
keyfile = "${EMQX_ETC_DIR}/certs/mirayai.com.key"
# 设置成 'verify_peer' 来验证客户端证书是否为 cacertfile 中某个根证书签发。双向认证时,必须设置成 'verify_peer'。
# 设置成 'verify_none' 则不验证客户端证书,即单向认证。
verify = verify_none
# 如果设置成 true,但是客户端在握手时候没有发送证书,服务端会终止握手。双向认证时,必须设置成 true。
# 如果设置成 false,那么服务端只有在客户端发送一个非法证书时才会终止握手
fail_if_no_peer_cert = false
}
}
listeners.wss.default {
bind = "0.0.0.0:8084"
max_connections = 1024000
websocket.mqtt_path = "/mqtt"
ssl_options {
certfile = "${EMQX_ETC_DIR}/certs/mirayai.com.pem"
keyfile = "${EMQX_ETC_DIR}/certs/mirayai.com.key"
cacertfile = "${EMQX_ETC_DIR}/certs/DigiCertGlobalRootCA.crt.pem"
verify = verify_none
fail_if_no_peer_cert = false
}
}完整配置
[root@iZwz9j7dbsko7t0h3sgas0Z emqx]# cat docker-compose.yml
services:
emqx1:
image: emqx/emqx:5.8.7
restart: always
hostname: emqx1
ports:
- 1883:1883
- 8883:8883
- 8083:8083
- 8084:8084
- 18083:18083
# - 4369:4369
# - 4370-4380:4370-4380
# - 5369:5369
# - 5370-5380:5370-5380
volumes:
- ./data:/opt/emqx/data # 启用数据持久化
- ./log:/opt/emqx/log # 启用日志持久化
- ./etc/certs:/opt/emqx/etc/certs # 挂载证书目录
- ./etc/emqx.conf:/opt/emqx/etc/emqx.conf # 挂载配置文件
environment:
TZ: "Asia/Shanghai"
EMQX_DASHBOARD__DEFAULT_PASSWORD: "mingrui@123"
EMQX_DEFAULT_LOG_HANDLER: file
# 开源版本不支持集群多节点持久化,只在单节点可以使用
## 集群配置(持久会话要求使用singleton模式)
EMQX_CLUSTER__DISCOVERY_STRATEGY: singleton # 集群发现策略设置为单例模式
EMQX_NODE__NAME: emqx@emqx.local # EMQX 采用 data/mnesia/<node_name> 目录进行数据存储,没有这个值,重启数据查不到
## 持久会话配置
EMQX_DURABLE_SESSIONS__ENABLE: true # 启用持久会话
EMQX_DURABLE_SESSIONS__BATCH_SIZE: 100 # 批处理大小
EMQX_DURABLE_SESSIONS__IDLE_POLL_INTERVAL: "1s" # 空闲轮询间隔
EMQX_DURABLE_SESSIONS__HEARTBEAT_INTERVAL: "10s" # 心跳间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_INTERVAL: "20h" # 会话垃圾回收间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_BATCH_SIZE: 100 # 垃圾回收批处理大小
# 用户认证配置(使用内置数据库)
EMQX_AUTHENTICATION__1__BACKEND: built_in_database # 认证后端类型为内置数据库
EMQX_AUTHENTICATION__1__ENABLE: true # 启用认证
EMQX_AUTHENTICATION__1__MECHANISM: password_based # 认证机制为密码认证
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__NAME: sha256 # 密码哈希算法为SHA256
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__SALT_POSITION: prefix # 盐值位置为前缀
EMQX_AUTHENTICATION__1__USER_ID_TYPE: username # 用户ID类型为用户名
# ACL配置(使用内置数据库)
EMQX_AUTHORIZATION__NO_MATCH: deny # 未匹配时拒绝访问
EMQX_AUTHORIZATION__SOURCES__1__TYPE: built_in_database # 授权类型为内置数据库
EMQX_AUTHORIZATION__SOURCES__1__ENABLE: true # 启用授权emqx+mongodb
用mongodb存储用户和ACL规则。
单节点配置
services:
mongodb:
image: mongo:8.0
restart: always
hostname: emqx
volumes:
- ./mongoDB/db:/data/db
environment:
TZ: "Asia/Shanghai"
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: a123456
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
emqx:
depends_on:
mongodb:
condition: service_healthy
image: emqx/emqx:5.8.7
restart: always
ports:
- 1883:1883
- 18083:18083
- 8083:8083
# volumes:
# - ./emqx-data:/opt/emqx/data
# - ./emqx-log:/opt/emqx/log
environment:
TZ: "Asia/Shanghai"
EMQX_DASHBOARD__DEFAULT_PASSWORD: "mingrui@123"
# 用户认证配置
EMQX_AUTHENTICATION__1__BACKEND: mongodb # 认证后端类型为MongoDB
EMQX_AUTHENTICATION__1__COLLECTION: mqtt_user # 用户信息集合名称
EMQX_AUTHENTICATION__1__DATABASE: emqx_auth # 认证数据库名称
EMQX_AUTHENTICATION__1__ENABLE: true # 启用认证
EMQX_AUTHENTICATION__1__FILTER: '{ "username": "$${username}" }' # 用户查询过滤器
EMQX_AUTHENTICATION__1__IS_SUPERUSER_FIELD: is_superuser # 超级用户标识字段
EMQX_AUTHENTICATION__1__MECHANISM: password_based # 认证机制为密码认证
EMQX_AUTHENTICATION__1__MONGO_TYPE: single # MongoDB部署类型为单节点
EMQX_AUTHENTICATION__1__PASSWORD: a123456 # MongoDB认证密码
EMQX_AUTHENTICATION__1__USERNAME: admin # MongoDB认证用户名
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__NAME: plain # 密码哈希算法为明文
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__SALT_POSITION: disable # 禁用密码加盐
EMQX_AUTHENTICATION__1__PASSWORD_HASH_FIELD: password # 密码字段名
EMQX_AUTHENTICATION__1__POOL_SIZE: 8 # 连接池大小
EMQX_AUTHENTICATION__1__SALT_FIELD: salt # 盐值字段名
EMQX_AUTHENTICATION__1__SERVER: "mongodb:27017" # MongoDB服务器地址
EMQX_AUTHENTICATION__1__SRV_RECORD: false # 禁用SRV记录
EMQX_AUTHENTICATION__1__SSL__ENABLE: false # 禁用SSL连接
EMQX_AUTHENTICATION__1__TOPOLOGY__CONNECT_TIMEOUT_MS: "20s" # 连接超时时间
EMQX_AUTHENTICATION__1__TOPOLOGY__HEARTBEAT_FREQUENCY_MS: "200s" # 心跳频率
EMQX_AUTHENTICATION__1__TOPOLOGY__MAX_OVERFLOW: 0 # 最大连接溢出数
EMQX_AUTHENTICATION__1__USE_LEGACY_PROTOCOL: "false" # 不使用旧版协议
# ACL配置
EMQX_AUTHORIZATION__NO_MATCH: deny # 未匹配时拒绝访问
EMQX_AUTHORIZATION__SOURCES__1__COLLECTION: mqtt_acl # ACL规则集合名称
EMQX_AUTHORIZATION__SOURCES__1__DATABASE: emqx_auth # 授权数据库名称
EMQX_AUTHORIZATION__SOURCES__1__ENABLE: true # 启用授权
EMQX_AUTHORIZATION__SOURCES__1__FILTER: '{ "username": "$${username}" }' # ACL查询过滤器
EMQX_AUTHORIZATION__SOURCES__1__MONGO_TYPE: single # MongoDB部署类型为单节点
EMQX_AUTHORIZATION__SOURCES__1__PASSWORD: a123456 # MongoDB认证密码
EMQX_AUTHORIZATION__SOURCES__1__POOL_SIZE: 8 # 连接池大小
EMQX_AUTHORIZATION__SOURCES__1__SERVER: "mongodb:27017" # MongoDB服务器地址
EMQX_AUTHORIZATION__SOURCES__1__SRV_RECORD: false # 禁用SRV记录
EMQX_AUTHORIZATION__SOURCES__1__SSL__ENABLE: false # 禁用SSL连接
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__CONNECT_TIMEOUT_MS: "20s" # 连接超时时间
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__HEARTBEAT_FREQUENCY_MS: "200s" # 心跳频率
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__MAX_OVERFLOW: 0 # 最大连接溢出数
EMQX_AUTHORIZATION__SOURCES__1__TYPE: mongodb # 授权类型为MongoDB
EMQX_AUTHORIZATION__SOURCES__1__USE_LEGACY_PROTOCOL: auto # 自动选择协议版本
EMQX_AUTHORIZATION__SOURCES__1__USERNAME: admin # MongoDB认证用户名添加 MQTT 用户
# 进入 MongoDB 容器
docker-compose exec mongodb mongosh -u admin -p a123456
# 切换到认证数据库
use emqx_auth
# 添加用户示例
db.mqtt_user.insertMany([
{
"username": "device001",
"password": "device123",
"is_superuser": false
},
{
"username": "admin_user",
"password": "admin123",
"is_superuser": true
},
{
"username": "sensor01",
"password": "sensor123",
"is_superuser": false
}
])查看用户:db.mqtt_user.find().pretty()
删除用户:db.mqtt_user.deleteMany({"username": "device001"})
为了防止重复用户数,可以为 username 字段创建唯一索引
db.mqtt_user.createIndex({"username": 1}, {"unique": true})
配置 ACL 权限
// 为 device001 添加权限
db.mqtt_acl.insertMany([
{
"username": "device001",
"action": "publish",
"permission": "allow",
"topic": "device/device001/+"
},
{
"username": "device001",
"action": "subscribe",
"permission": "allow",
"topic": "device/device001/+"
},
{
"username": "device001",
"action": "subscribe",
"permission": "allow",
"topic": "command/device001/+"
},
// 为 sensor01 添加权限
{
"username": "sensor01",
"action": "publish",
"permission": "allow",
"topic": "sensor/+/data"
},
{
"username": "sensor01",
"action": "subscribe",
"permission": "deny",
"topic": "admin/+"
},
// 超级用户通常不需要 ACL 规则,因为 is_superuser: true
])查看 ACL 规则:db.mqtt_acl.find().pretty()
删除ACL 规则:db.mqtt_acl.deleteMany({"username": "device001"})
完整配置
services:
mongodb:
image: mongo:8.0
restart: always
volumes:
- ./mongoDB/db:/data/db
environment:
TZ: "Asia/Shanghai"
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: a123456
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
emqx:
depends_on:
mongodb:
condition: service_healthy
image: emqx/emqx:5.8.7
restart: always
ports:
- 1883:1883
- 18083:18083
- 8083:8083
volumes:
- ./emqx-data:/opt/emqx/data # 启用数据持久化
- ./emqx-log:/opt/emqx/log # 启用日志持久化
environment:
TZ: "Asia/Shanghai"
EMQX_DASHBOARD__DEFAULT_PASSWORD: "mingrui@123"
# 集群配置(持久会话要求使用singleton模式)
EMQX_CLUSTER__DISCOVERY_STRATEGY: singleton # 集群发现策略设置为单例模式
EMQX_NODE__NAME: emqx@emqx.local # EMQX 采用 data/mnesia/<node_name> 目录进行数据存储,没有这个值,重启数据查不到
# 持久会话配置
EMQX_DURABLE_SESSIONS__ENABLE: true # 启用持久会话
EMQX_DURABLE_SESSIONS__BATCH_SIZE: 100 # 批处理大小
EMQX_DURABLE_SESSIONS__IDLE_POLL_INTERVAL: "1s" # 空闲轮询间隔
EMQX_DURABLE_SESSIONS__HEARTBEAT_INTERVAL: "10s" # 心跳间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_INTERVAL: "20h" # 会话垃圾回收间隔
EMQX_DURABLE_SESSIONS__SESSION_GC_BATCH_SIZE: 100 # 垃圾回收批处理大小
# 用户认证配置
EMQX_AUTHENTICATION__1__BACKEND: mongodb # 认证后端类型为MongoDB
EMQX_AUTHENTICATION__1__COLLECTION: mqtt_user # 用户信息集合名称
EMQX_AUTHENTICATION__1__DATABASE: emqx_auth # 认证数据库名称
EMQX_AUTHENTICATION__1__ENABLE: true # 启用认证
EMQX_AUTHENTICATION__1__FILTER: '{ "username": "$${username}" }' # 用户查询过滤器
EMQX_AUTHENTICATION__1__IS_SUPERUSER_FIELD: is_superuser # 超级用户标识字段
EMQX_AUTHENTICATION__1__MECHANISM: password_based # 认证机制为密码认证
EMQX_AUTHENTICATION__1__MONGO_TYPE: single # MongoDB部署类型为单节点
EMQX_AUTHENTICATION__1__PASSWORD: a123456 # MongoDB认证密码
EMQX_AUTHENTICATION__1__USERNAME: admin # MongoDB认证用户名
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__NAME: plain # 密码哈希算法为明文
EMQX_AUTHENTICATION__1__PASSWORD_HASH_ALGORITHM__SALT_POSITION: disable # 禁用密码加盐
EMQX_AUTHENTICATION__1__PASSWORD_HASH_FIELD: password # 密码字段名
EMQX_AUTHENTICATION__1__POOL_SIZE: 8 # 连接池大小
EMQX_AUTHENTICATION__1__SALT_FIELD: salt # 盐值字段名
EMQX_AUTHENTICATION__1__SERVER: "mongodb:27017" # MongoDB服务器地址
EMQX_AUTHENTICATION__1__SRV_RECORD: false # 禁用SRV记录
EMQX_AUTHENTICATION__1__SSL__ENABLE: false # 禁用SSL连接
EMQX_AUTHENTICATION__1__TOPOLOGY__CONNECT_TIMEOUT_MS: "20s" # 连接超时时间
EMQX_AUTHENTICATION__1__TOPOLOGY__HEARTBEAT_FREQUENCY_MS: "200s" # 心跳频率
EMQX_AUTHENTICATION__1__TOPOLOGY__MAX_OVERFLOW: 0 # 最大连接溢出数
EMQX_AUTHENTICATION__1__USE_LEGACY_PROTOCOL: "false" # 不使用旧版协议
# ACL配置
EMQX_AUTHORIZATION__NO_MATCH: deny # 未匹配时拒绝访问
EMQX_AUTHORIZATION__SOURCES__1__COLLECTION: mqtt_acl # ACL规则集合名称
EMQX_AUTHORIZATION__SOURCES__1__DATABASE: emqx_auth # 授权数据库名称
EMQX_AUTHORIZATION__SOURCES__1__ENABLE: true # 启用授权
EMQX_AUTHORIZATION__SOURCES__1__FILTER: '{ "username": "$${username}" }' # ACL查询过滤器
EMQX_AUTHORIZATION__SOURCES__1__MONGO_TYPE: single # MongoDB部署类型为单节点
EMQX_AUTHORIZATION__SOURCES__1__PASSWORD: a123456 # MongoDB认证密码
EMQX_AUTHORIZATION__SOURCES__1__POOL_SIZE: 8 # 连接池大小
EMQX_AUTHORIZATION__SOURCES__1__SERVER: "mongodb:27017" # MongoDB服务器地址
EMQX_AUTHORIZATION__SOURCES__1__SRV_RECORD: false # 禁用SRV记录
EMQX_AUTHORIZATION__SOURCES__1__SSL__ENABLE: false # 禁用SSL连接
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__CONNECT_TIMEOUT_MS: "20s" # 连接超时时间
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__HEARTBEAT_FREQUENCY_MS: "200s" # 心跳频率
EMQX_AUTHORIZATION__SOURCES__1__TOPOLOGY__MAX_OVERFLOW: 0 # 最大连接溢出数
EMQX_AUTHORIZATION__SOURCES__1__TYPE: mongodb # 授权类型为MongoDB
EMQX_AUTHORIZATION__SOURCES__1__USE_LEGACY_PROTOCOL: auto # 自动选择协议版本
EMQX_AUTHORIZATION__SOURCES__1__USERNAME: admin # MongoDB认证用户名emqx集群持久化
开源版本不支持集群持久化,只能使用单节点持久化
EMQX开源版的持久会话功能确实支持S3存储,但 仅限于单节点部署 。在集群模式下,开源版只能使用内置存储(builtin_local),且集群发现策略必须设置为 singleton 。
持久会话的高可用复制功能是企业版特性,开源版无法在集群中复制持久会话数据。
https://github.com/emqx/emqx/discussions/14522
https://docs.emqx.com/zh/emqx/latest/durability/durability_introduction.html