Ubuntu上搭建mosquitto MQTT服务器:安装配置与避坑指南
2026/9/15 23:49:47 网站建设 项目流程

手头正好在调的物联网项目需要一台内网消息服务器,选来选去还是回到mosquitto上。如果你也在Ubuntu上折腾MQTT服务器,这篇直接把安装、配置、鉴权、踩坑一次讲透,照着抄就行。

1. 为什么是mosquitto:轻量级MQTT服务器的选型逻辑

先聊清楚一个基本问题:MQTT服务器那么多,为什么偏偏用mosquitto?

MQTT协议本身是发布/订阅模型,客户端通过Broker中转消息,而不是点对点直连。这种模式下,Broker就是整个消息体系的心脏——所有设备的消息都要经过它,它的稳定性、并发能力直接决定业务能不能扛住。

mosquitto是Eclipse基金会维护的开源项目,纯C语言实现,核心优势就一个字:轻。我实测过,默认配置下内存占用不到10MB,在树莓派、工控机、云服务器上都能跑。对比其他方案会更直观:

项目语言内存占用适合场景上手难度
mosquittoC10-20MB中小规模、边缘设备、内网部署
EMQXErlang500MB+百万级连接、集群部署
HiveMQJava1GB左右企业级、商业支持
VerneMQErlang500MB+高可用集群

如果你的业务是几千台设备、每秒几百条消息这个量级,mosquitto完全够用。它默认支持MQTT 3.1.1和5.0协议,还支持WebSocket、TLS加密、多用户鉴权,功能上不虚商业产品。

另一个让我选它的理由是配置极简。核心配置文件就一个mosquitto.conf,几个关键参数一设置,服务就能跑起来。相比EMQX那种附带一堆插件、Dashboard的庞然大物,mosquitto更像一个专注做一件事的小工具,适合自己掌控细节。

注意:如果你预估未来设备量会增长到十万级以上,建议从一开始就考虑EMQX这类集群方案,避免后期迁移成本。mosquitto单节点扛个几千到几万连接没问题,但大规模并发会吃紧。

2. 部署前的环境梳理:版本、端口与资源预检

动手安装之前,把环境摸清楚能省掉后面一大半的坑。

2.1 Ubuntu版本确认

不同Ubuntu版本自带的mosquitto版本不一样,这直接影响你能否用到新特性(比如MQTT 5.0)。先确认系统版本:

lsb_release -a
  • Ubuntu 20.04 LTS:默认源里是mosquitto 1.6.x,支持MQTT 5.0,但WebSocket和TLS配置语法稍旧。
  • Ubuntu 22.04 LTS:默认源里是mosquitto 2.0.x,这是目前最稳的版本,结构清晰,权限管理变严格了。
  • Ubuntu 24.04 LTS:软件源里mosquitto还是2.0.x系列,但相关库更新,编译环境更好。

我建议直接用Ubuntu 22.04及以上,mosquitto 2.0之后把include_dirper_listener_settingsallow_anonymous的默认值都改了,更安全也更合理。2.0之前,默认允许匿名连接;2.0之后,默认allow_anonymous false,你如果不显式配置,客户端根本连不上——这是个大变化,下面会细说。

2.2 端口规划

MQTT默认端口是1883,但实际部署至少要规划这几个:

端口用途协议
1883标准MQTT通信MQTT over TCP
8883TLS加密通信MQTT over SSL/TLS
8083WebSocket通信MQTT over WebSocket
8084WebSocket + TLSMQTT over WSS

内网测试只开放1883就够了。如果要对接浏览器端的前端页面,需要加一个WebSocket端口。对外网开放且有安全要求,就得考虑TLS端口8883/8084。

检查端口是否被占用:

ss -lntp | grep 1883

如果端口被占用,用这条命令查是哪个进程占的:

lsof -i :1883

2.3 防火墙与安全组

这是新手最容易忽略的。Ubuntu默认可能开着ufw防火墙,如果不开端口,外部访问会直接超时:

sudo ufw allow 1883/tcp sudo ufw allow 8883/tcp sudo ufw allow 8083/tcp sudo ufw status

如果你用的是云服务器(阿里云、腾讯云、华为云等),除了系统防火墙,还得去云控制台的安全组里放行对应端口。安全组是云平台层面做的网络隔离,和系统防火墙是两层独立的过滤,只开一处是连不通的。

2.4 系统资源预检

mosquitto虽然轻,但也要确认基础资源够用:

free -h # 查看内存 df -h # 查看磁盘剩余 cat /proc/cpuinfo | grep processor | wc -l # 查看CPU核心数

一个经验值:单核CPU、512MB内存的小机器,能扛住几千个长连接、每秒几百条消息的负载。如果消息量再大,优先考虑调参(后面会讲),而不是加机器。

3. 安装实操:apt一键安装与源码编译两条路线

3.1 apt安装:最快路径

官方源里已经有mosquitto,装起来非常省事:

sudo apt update sudo apt install -y mosquitto mosquitto-clients

这里有个关键点:mosquitto-clients一定要装。它包含了mosquitto_pubmosquitto_sub两个命令行工具,测试服务是否正常全靠它们。

安装完成后,服务会自动启动并设置开机自启。确认状态:

systemctl status mosquitto

如果运行中,会显示active (running)。同时检查端口监听:

sudo ss -lntp | grep 1883

看到LISTEN状态就说明服务已经起来了。

服务管理常用命令:

sudo systemctl restart mosquitto # 重启 sudo systemctl stop mosquitto # 停止 sudo systemctl start mosquitto # 启动 sudo systemctl enable mosquitto # 设置开机自启 sudo systemctl disable mosquitto # 取消开机自启

apt装的好处是:后续升级直接sudo apt update && sudo apt upgrade就能自动更新,和系统包管理无缝集成。缺点是版本可能不是最新的,也不能自定义编译参数。

3.2 源码编译:当apt版本不够用时

什么情况需要源码编译?

  1. 想用比apt源更新的版本,比如需要特定补丁。
  2. 想开启第三方插件支持,比如动态安全插件。
  3. 想定制安装路径、启用调试日志。

源码编译步骤如下:

# 安装编译依赖 sudo apt install -y build-essential libssl-dev libc-ares-dev uuid-dev libwebsockets-dev cmake # 下载源码(以2.0.18为例) cd /tmp wget https://github.com/eclipse-mosquitto/mosquitto/archive/refs/tags/v2.0.18.tar.gz tar -xzf v2.0.18.tar.gz cd mosquitto-2.0.18 # 编译安装 mkdir build && cd build cmake .. make -j$(nproc) sudo make install

编译装完,会默认装到/usr/local目录,可执行文件在/usr/local/sbin/mosquitto。这时候要注意:apt版的两个服务启动方式就用不上了,需要手动启动或者自己写systemd服务文件。

验证版本:

/usr/local/sbin/mosquitto -h

经验之谈:90%的场景用apt就够。源码编译适合想折腾、想用新特性的开发者,对于生产环境,我反而推荐用apt稳定版——经过发行版团队充分测试,出问题也好排查。

3.3 安装目录与文件布局

不管用哪种方式装,装完之后有几个关键文件路径要搞清:

文件/目录用途
/etc/mosquitto/mosquitto.conf主配置文件
/etc/mosquitto/conf.d/附加配置目录(会被主配置自动引入)
/var/log/mosquitto/日志目录
/var/lib/mosquitto/持久化数据目录
/usr/sbin/mosquittomosquitto主程序(apt版)

理解这个布局很重要:主配置文件会通过include_dir一行引入/etc/mosquitto/conf.d/下所有.conf文件。这意味着你可以把不同功能拆分到不同配置文件里,比如auth.conf放认证配置、websocket.conf放WebSocket配置,方便管理。

4. 手把手配置:从零写一份能用的mosquitto.conf

mosquitto的默认配置非常保守,跑通基础通信前,你需要理解这几个核心参数。我直接给一份注释完整的配置,你照着改就行。

4.1 最小可用配置

# /etc/mosquitto/mosquitto.conf # 监听1883端口,接受所有网络接口的连接 listener 1883 0.0.0.0 # 允许匿名连接(生产环境务必改成false) allow_anonymous true # 消息持久化开关 persistence true persistence_location /var/lib/mosquitto/ # 日志输出到终端(方便调试) log_dest stdout log_dest topic log_type all

这份配置的核心是listenerallow_anonymous

listener 1883 0.0.0.0的意思是:在1883端口上监听,绑定所有网络接口。这里有个大坑——如果你写listener 1883 127.0.0.1,服务只能被本机访问,外部设备怎么都连不上。所以地址写0.0.0.0才能对外提供服务。

allow_anonymous true是允许无账号密码直接连接。这仅限内网调试,正式环境必须改成false,否则任何人都能往你的topic里发消息。

这份配置对应的完整操作路径:

# 备份默认配置 sudo cp /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf.bak # 编辑配置 sudo nano /etc/mosquitto/mosquitto.conf # 修改后重启服务 sudo systemctl restart mosquitto # 查看运行状态和日志 sudo systemctl status mosquitto tail -f /var/log/mosquitto/mosquitto.log

4.2 配置项的语义拆解

listener:监听端口和绑定地址,可以写多个listener实现多端口监听。比如同时监听1883和8083(WebSocket)。

allow_anonymous:是否允许匿名连接。true允许,false禁止。2.0版本默认是false,这意味着你如果直接apt装完想匿名测试,必须显式改为true

persistence:是否把消息持久化到磁盘。开启后,Broker重启时能恢复掉线前的会话和离线消息。如果只是内网小规模测试,开不开无所谓;生产环境建议开启。

log_type:日志级别。all表示记录所有类型的日志,error只记错误,warning记录警告和错误。正式跑调error就行,避免日志暴涨。

4.3 一份生产级配置模板

# /etc/mosquitto/mosquitto.conf # 标准MQTT端口 listener 1883 0.0.0.0 # WebSocket端口 listener 8083 0.0.0.0 protocol websockets # 安全配置 allow_anonymous false password_file /etc/mosquitto/passwd # 持久化 persistence true persistence_location /var/lib/mosquitto/ # 日志 log_dest file /var/log/mosquitto/mosquitto.log log_type error log_type warning log_type notice # 连接限制(可选) max_connections -1 message_size_limit 0 max_inflight_messages 20 max_queued_messages 1000

protocol websockets这行指定8083端口使用WebSocket协议。后面接max_connections -1表示不限制连接数,message_size_limit 0表示不限制单条消息大小,max_inflight_messagesmax_queued_messages控制客户端消息队列行为。

5. 端到端联调测试:命令行和Python双路径

服务配置好、重启完,下一步就是验证Broker真的能干活了。

5.1 用mosquitto_clients做冒烟测试

打开两个终端窗口。

终端A——订阅一个主题:

mosquitto_sub -h 127.0.0.1 -p 1883 -t 'test/topic' -v

-h指定Broker地址,-p指定端口,-t指定订阅主题,-v让输出带主题名。

终端B——发布一条消息:

mosquitto_pub -h 127.0.0.1 -p 1883 -t 'test/topic' -m 'hello from mqtt'

如果配置正确,终端A能看到test/topic hello from mqtt输出,说明Broker正常转发消息。

验证外部设备能不能连:把-h 127.0.0.1换成Broker所在机器的局域网IP(比如192.168.x.x),从另一台设备执行同样的命令。如果连不上,回头查防火墙、bind_address。

5.2 用Python脚本验证复杂场景

命令行工具只能做基础验证,实际业务里我更推荐用Python+paho-mqtt库做完整测试:

安装依赖:

pip3 install paho-mqtt

订阅端脚本:

# sub.py import paho.mqtt.client as mqtt BROKER = "127.0.0.1" PORT = 1883 TOPIC = "sensor/temperature" def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to broker") client.subscribe(TOPIC, qos=1) else: print(f"Connection failed, code={rc}") def on_message(client, userdata, msg): print(f"Topic: {msg.topic}, Payload: {msg.payload.decode()}") client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(BROKER, PORT, 60) client.loop_forever()

发布端脚本:

# pub.py import paho.mqtt.client as mqtt import time import random BROKER = "127.0.0.1" PORT = 1883 TOPIC = "sensor/temperature" client = mqtt.Client() client.connect(BROKER, PORT, 60) for i in range(10): temp = round(random.uniform(20.0, 30.0), 2) payload = f"{{'temp': {temp}}}" client.publish(TOPIC, payload, qos=1) print(f"Published: {payload}") time.sleep(1) client.disconnect()

运行:

python3 sub.py # 终端A python3 pub.py # 终端B

订阅端会连续输出10条温度数据。qos=1表示消息至少送达一次,适合对数据完整性有要求的场景。这套脚本可以用作后续业务开发的基础模板。

6. 上生产前的安全与高可用配置

6.1 账号密码鉴权:不能裸奔

allow_anonymous true只能用来第一步打通流程。一旦要正式接设备,第一件事就是关掉匿名,启用账号密码:

# 创建密码文件,-c参数表示新建 sudo mosquitto_passwd -c /etc/mosquitto/passwd admin # 追加用户(不加-c) sudo mosquitto_passwd /etc/mosquitto/passwd device001

交互式命令会两次输入密码。配置文件里开启:

allow_anonymous false password_file /etc/mosquitto/passwd

重启后,所有客户端都必须带用户名密码才能连接:

mosquitto_sub -h 127.0.0.1 -p 1883 -t 'test/topic' -u admin -P '你的密码'

注意:在2.0版本中,如果allow_anonymous false但又没配置password_file,会导致所有连接都被拒绝。这两个参数是配合使用的,别漏配。

6.2 WebSocket接入:让浏览器也能直连

物联网项目经常会做Web端实时监控面板。如果直接用前端连1883端口,会撞上浏览器对TCP连接的限制,所有现代浏览器都不支持原生TCP Socket。解决办法是让mosquitto提供WebSocket端口。

在配置文件加一段:

listener 8083 0.0.0.0 protocol websockets allow_anonymous false password_file /etc/mosquitto/passwd

前端用mqtt.js库连接:

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script> <script> const client = mqtt.connect('ws://192.168.1.100:8083', { username: 'admin', password: '你的密码' }); client.on('connect', function () { console.log('Connected via WebSocket'); client.subscribe('sensor/temperature'); }); client.on('message', function (topic, message) { document.getElementById('temp').innerText = message.toString(); }); </script>

这里ws://不是加密的,如果跨公网传数据,建议用wss://加TLS。

6.3 性能参数调优:适当放开手脚

默认配置是保守参数,高并发场景需要调整几个关键值:

# 单客户端最大并发未确认消息数 max_inflight_messages 50 # 单客户端最大排队消息数 max_queued_messages 5000 # 允许的最大连接数,-1不限制 max_connections 10000 # 每秒最大消息数,0不限制 max_qos 2

这些参数调高会增加内存占用,但能让高吞吐场景下不丢消息。内存占用公式大概是:每万条排队消息约多占几十MB。根据自己硬件条件调整。

6.4 TLS加密:比你想的更简单

如果数据要经过公网传输,明文收包的风险很大。用mosquitto配TLS并没那么复杂,核心是签证书、配路径、开端口。

生成自签名证书:

# 生成私钥 openssl genrsa -out ca.key 2048 # 生成证书签名请求 openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=my-mqtt-server" # 自签名证书 openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt

配置文件加:

listener 8883 0.0.0.0 cafile /etc/mosquitto/certs/ca.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key

客户端连接时带上CA证书:

mosquitto_sub -h 你的域名 -p 8883 -t 'test/topic' --cafile /path/to/ca.crt

提示:自签名证书只适合内网和开发环境。生产环境建议用Let's Encrypt申请免费证书,代价是需要一个公网域名。

7. 踩坑实录:Ubuntu上装mosquitto最常见的6个问题

从零开始配置mosquitto,几乎人人都会遇到下面这几个坑。我把完整的排查链路写出来,下次遇到直接照方抓药。

7.1 外部设备连不上,本机能连

这是频率最高的问题。如果mosquitto_sub -h 127.0.0.1能连,换成局域网IP就超时,排查顺序:

  1. 确认listener绑定的地址:配置文件里是不是写了listener 1883 127.0.0.1?改成0.0.0.0
  2. 确认systemd覆盖配置:2.0版本安装后,/etc/mosquitto/conf.d/里可能有一个local.conf,里面写了listener 1883 localhost,它会覆盖主配置。删掉或改掉。
  3. 查防火墙sudo ufw status看1883端口是否放行。
  4. 查云安全组:云控制台确认入方向规则放行1883。
  5. 用tcpdump抓包验证sudo tcpdump -i any port 1883 -n,看客户端SYN包是否到达服务器。如果抓不到包,说明网络路径被挡在服务器之外。

7.2 allow_anonymous配置后没生效

出现权限错误Connection Refused: not authorised,说明连接被拒绝。检查:

  • 配置文件是否真的被正确加载:mosquitto -c /etc/mosquitto/mosquitto.conf手动启动一遍,看有没有语法报错。
  • 是否被conf.d下的文件覆盖:2.0版本的local.conf可能包含allow_anonymous false,注意加载顺序。
  • 语法是否错误:allow_anonymous true放的位置是否正确,缩进无要求,但参数名不能写错。

7.3 密码认证不生效

password_file /etc/mosquitto/passwd配置了,但还是能匿名连,或者有密码的连不上。重点检查:

  • allow_anonymous false是否显式配置了(默认false,但显式写更稳妥)。
  • 密码文件权限:sudo chmod 644 /etc/mosquitto/passwd,如果密码文件被其他用户读完,mosquitto会拒绝加载。
  • 密码文件路径是否正确:可以用sudo mosquitto_passwd -U /etc/mosquitto/passwd更新密码哈希。

7.4 systemd服务启动失败

systemctl status mosquitto显示失败,用journalctl -u mosquitto -n 50查日志。常见原因:

  • 配置文件语法错误:mosquitto -c /etc/mosquitto/mosquitto.conf手动跑,看到Error: Invalid input这类就是语法问题。
  • 数据目录权限:sudo chown -R mosquitto:mosquitto /var/lib/mosquitto/
  • 端口被占用:杀掉占进程,或换端口。

7.5 日志不输出

想排查问题但日志文件是空的。检查:

  • 配置文件里log_dest file /var/log/mosquitto/mosquitto.log,注意目录要存在且可写。
  • 更省心的是直接log_dest stdout,日志直接打到systemd,journalctl -u mosquitto -f就能实时看。

7.6 客户端连接后反复断开(KeepAlive参数问题)

有些设备设置的心跳间隔太短,比如每1秒发一次心跳,Broker可能跟不上。在配置里放宽:

# 单位秒,超过这个时间没收到消息就断开连接 keepalive_interval 65

一般客户端默认心跳是60秒,服务器端限制放宽到65秒比较稳妥,留出网络抖动余量。

8. 我的使用心得和后续扩展方向

把mosquitto吃透之后,你会发现它确实是最不会骗人的那种软件——配置就是配置,没有花哨的东西,但每一个参数都实实在在影响行为。

我自己在几台Ubuntu设备上的部署习惯是:apt安装 + 显式配置 + 账号密码鉴权,三件事缺一不可。apt安装保证升级路径清晰;显式配置避免被默认值坑;账号密码是底线,哪怕只是内网测试也要开。如果只是自己测试,懒一点可以先用匿名模式跑通,但准备接真实设备的第一天就把allow_anonymous false加上,不然哪天公网IP暴露了,整个Broker就像没锁门的仓库。

日志一定要接出来。我吃过一次亏:生产环境有个设备上报异常,Broker没报错,客户端也没报错,但消息就是收不到。最后查日志发现是持久化报错——磁盘满了。如果当时没开日志,这个bug怕是要查一晚上。

后续想进阶,这几个方向可以继续折腾:

  • ACL访问控制:按用户名限制可订阅/发布的主题,做设备级隔离。比如device001只能发device001/#,不能窜到别的设备主题里去。
  • 桥接模式:多个mosquitto实例之间做桥接,实现跨机房消息同步,很适合分布式场景。
  • 集群方案:单机扛不住时,在mosquitto上层加负载均衡,或者平滑迁移到EMQX。
  • 监控接入:开启log_type all,用Prometheus+Grafana采集mosquitto的指标,连接数、消息数一目了然。

搭建本身是五分钟的事,真正有价值的是理解Broker的转发逻辑、鉴权机制、队列行为,这些东西在规模化后全是关键决策点。希望这套踩坑笔记能让你少走几步弯路,一次跑通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询