RMQTT 0.24.0 MQTT Broker on AWS User Guide
Overview
This guide covers launching and using the RMQTT 0.24.0 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg streaming and messaging listing on AWS Marketplace; you pick it as the software version when you subscribe.
RMQTT is an open source (MIT) MQTT broker written in Rust. It serves MQTT versions 5.0 and 3.1.1, the publish/subscribe protocol used by IoT devices, sensors, vehicles, home automation and mobile apps. Clients publish messages to topics (such as sensors/17/temperature) and the broker delivers them to every client subscribed to a matching topic filter (such as sensors/+/temperature or sensors/#). Any MQTT client works with it: the Mosquitto command-line tools mosquitto_pub and mosquitto_sub, Eclipse Paho (Python, Java, C, Go, JavaScript), MQTT.js, HiveMQ client libraries and others.
What the cloudimg image adds:
- MQTT over TLS only. Clients reach the broker on 8883 (MQTT over TLS 1.3 or 1.2 with AEAD cipher suites only). RMQTT's usual clear-text port 1883, its internal port 11883, WebSockets (8080 and 8443), QUIC (9443) and the HTTP management API (6060) are not configured, so nothing answers on them even if a security group allows them (Step 10).
- A certificate made on your instance. At first boot the broker gets a TLS key and an end-entity certificate for this instance's own names and addresses. It can only vouch for this broker and can never sign other certificates. You pin it in your clients (Step 5), or replace it with one from your own CA or Let's Encrypt (Step 12).
- No anonymous access and no default password. Every client logs in. First boot generates a login unique to your instance,
cloudimg-app, with a 128-bit random password. Passwords are stored only as salted PBKDF2-SHA256 hashes, in a file the broker process itself cannot read: a separate login service,rmqtt-authd, checks them on the loopback address. - Every login confined to its own topic tree. The topic rules let each login publish and subscribe only under
<login>/#(socloudimg-appusescloudimg-app/#) and deny everything else, including#and$SYS/#. There is no superuser (Step 8). - Users you can manage safely.
rmqtt-useradds a login with its password read from standard input (never a command line). A new login works at once, with no restart (Step 8). - A broker that refuses to run unsafely. Before every start a configuration gate refuses an unsafe change (a clear-text, WebSocket or QUIC listener, anonymous clients, the HTTP API, the cluster port on a public address, topic rules that end by allowing, a login service that fails open). After every start a guard checks the running broker's sockets, logins and network rules, and stops it if anything is wrong. If first boot cannot finish, the broker never serves (Step 9).
- No telemetry, no instance metadata, no outbound network. RMQTT has no telemetry. The broker and the login service run with the EC2 instance metadata address blocked, and a firewall table lets the broker's user reach nothing but the login service: every outbound connection, including to your own VPC, is refused (Step 11).
- A pinned supply chain. The
rmqttdbinary comes from the RMQTT project's GitHub release0.24.0(rmqtt-0.24.0-x86_64-unknown-linux-musl.zip), checked against its SHA-256 digest, with every shipped file recorded in/usr/share/doc/cloudimg-rmqtt/PROVENANCE. Ubuntu 24.04 LTS is fully patched at build time.
What is on the image: RMQTT 0.24.0 (/usr/local/bin/rmqttd; configuration in /etc/rmqtt/rmqtt.toml, plugin settings in /etc/rmqtt/plugins/, logins in /etc/rmqtt-auth/), the plugins rmqtt-acl (topic rules), rmqtt-auth-http (logins, checked by rmqtt-authd), rmqtt-retainer (retained messages) and rmqtt-shared-subscription, and the cloudimg helpers rmqtt-probe (an MQTT test client), rmqtt-selfcheck, rmqtt-user, rmqtt-set-hostname, rmqtt-install-cert and rmqtt-config-gate.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 22 | TCP | your admin network | SSH |
| 8883 | TCP | the networks your MQTT clients connect from | MQTT over TLS |
Nothing else needs to be open. Ports 1883 and 11883 (clear-text MQTT), 8080 and 8443 (WebSockets), 9443 (QUIC), 6060 (HTTP API) and 5363 (cluster gRPC) are not served to the network, so opening them achieves nothing.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick RMQTT 0.24.0 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (or larger for many thousands of connections or high message rates), your key pair and a security group as above.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=rmqtt-broker}]'
The image requires IMDSv2 (session tokens). First boot takes under a minute after the instance is running: the boot service reads the instance's EC2 names, creates the login and the certificate, then the login service and the broker start and the guard checks them.
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| RMQTT 0.24.0 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
The login banner shows where the login and the certificate are:
RMQTT 0.24.0 on Ubuntu 24.04 (cloudimg)
Login, endpoint, certificate fingerprint: sudo cat /root/rmqtt-credentials.txt
Clients: MQTT over TLS only, mqtts://<this host>:8883 (pin /etc/rmqtt/tls/cert.pem); topics <login>/#
Broker: systemctl status rmqtt journalctl -u rmqtt Verify: sudo rmqtt-selfcheck Users: sudo rmqtt-user list
User guide: https://www.cloudimg.co.uk/guides/rmqtt-0-24-0-on-ubuntu-24-04-aws/
Step 3: Check the services and the listening set
systemctl is-active rmqtt-metadata-names rmqtt-firstboot rmqtt-egress-guard rmqtt-authd rmqtt
sudo ss -tlnp | grep -E ':(22|80|443|960|1883|5363|6060|8080|8443|8883|11883) '
sudo ss -ulnp | grep -E 'rmqtt|python3' || echo 'no UDP socket'
active
active
active
active
active
LISTEN 0 1024 0.0.0.0:8883 0.0.0.0:* users:(("rmqttd",pid=1057,fd=10))
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1059,fd=3),("systemd",pid=1,fd=57))
LISTEN 0 128 127.0.0.1:5363 0.0.0.0:* users:(("rmqttd",pid=1057,fd=9))
LISTEN 0 256 127.0.0.1:960 0.0.0.0:* users:(("python3",pid=1050,fd=3))
LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1059,fd=4),("systemd",pid=1,fd=58))
no UDP socket
rmqtt-metadata-names reads this instance's EC2 names for the certificate, rmqtt-firstboot prepares the login and the certificate, rmqtt-egress-guard loads the broker's firewall table, rmqtt-authd is the login service and rmqtt is the broker. The broker listens on 8883 (every IPv4 address) for clients. RMQTT always starts a cluster gRPC server; it is bound to 127.0.0.1:5363, and the firewall table refuses it even on the loopback address, because this image runs a single node. The login service listens on 127.0.0.1:960 only, a privileged port no ordinary user can take over, and only the broker's user may connect to it.
Step 4: Your endpoint and login
Everything generated for your instance is in /root/rmqtt-credentials.txt (readable by root only). View it all with sudo cat /root/rmqtt-credentials.txt. The lines that are not secret are:
sudo grep -E '^RMQTT_(HOST|URL|PORT|PRIVATE_IP|USER|TOPIC_PREFIX|TLS_CA_FILE|TLS_CERT_SHA256|TLS_PUBKEY_SHA256)=' /root/rmqtt-credentials.txt
RMQTT_HOST=34.227.171.134
RMQTT_URL=mqtts://34.227.171.134:8883
RMQTT_PORT=8883
RMQTT_PRIVATE_IP=172.31.87.173
RMQTT_USER=cloudimg-app
RMQTT_TOPIC_PREFIX=cloudimg-app/
RMQTT_TLS_CA_FILE=/etc/rmqtt/tls/cert.pem
RMQTT_TLS_CERT_SHA256=4D:42:56:C6:24:0A:F6:AB:3B:67:E3:3B:00:93:52:1C:3F:F2:23:53:13:6C:03:6D:3E:DC:CD:B3:65:3B:66:A0
RMQTT_TLS_PUBKEY_SHA256=ea1916b7c208fe504d4fb1d553d000e5b4e6cb6a2d17924a70d8981d7cb1365d
The file also holds RMQTT_PASSWORD, the password of cloudimg-app. That login may use only topics that start with cloudimg-app/. Give each device type or application a login of its own (Step 8) rather than sharing this one. Keep passwords in files with mode 0600, not in shell history or on command lines (a command line is visible to every user on a machine through ps).
Step 5: Check the certificate and pin it in your client
The broker's certificate is self-signed, made on your instance:
sudo openssl x509 -in /etc/rmqtt/tls/cert.pem -noout -subject -enddate -ext subjectAltName,basicConstraints
sudo openssl x509 -in /etc/rmqtt/tls/cert.pem -noout -fingerprint -sha256
subject=CN = rmqtt-broker, O = cloudimg
notAfter=Feb 10 10:46:46 2029 GMT
X509v3 Subject Alternative Name:
IP Address:34.227.171.134, DNS:ec2-34-227-171-134.compute-1.amazonaws.com, IP Address:172.31.87.173, DNS:ip-172-31-87-173.ec2.internal, IP Address:127.0.0.1, DNS:localhost
X509v3 Basic Constraints: critical
CA:FALSE
sha256 Fingerprint=4D:42:56:C6:24:0A:F6:AB:3B:67:E3:3B:00:93:52:1C:3F:F2:23:53:13:6C:03:6D:3E:DC:CD:B3:65:3B:66:A0
CA:FALSE means it is an end-entity certificate that cannot sign anything else. The SHA-256 fingerprint is the RMQTT_TLS_CERT_SHA256 value in your credentials file. Copy the certificate (it is public; the private key never leaves the instance) to each client machine:
client-host$ ssh -i <your-key.pem> ubuntu@<public-ip> 'sudo cat /etc/rmqtt/tls/cert.pem' > rmqtt.crt
client-host$ openssl x509 -in rmqtt.crt -noout -fingerprint -sha256
Compare the fingerprint with RMQTT_TLS_CERT_SHA256 before you trust the file. Then give your client only this file as its CA file (--cafile for mosquitto_pub and mosquitto_sub, tls_set(ca_certs=...) in Paho), with host name checking on. Do not add it to the operating system's trust store: the client should trust this one broker, not every program on the machine. Your client will then refuse any other server, including one in the middle that presents a different certificate. A client that uses only its system trust store is refused with CERTIFICATE_VERIFY_FAILED.
The certificate covers the instance's public and private IPv4 addresses and EC2 DNS names, localhost and 127.0.0.1. An EC2 stop and start gives the instance a new public IP. At the next boot the certificate is re-issued for the new names with the same key: clients that pin the public key (RMQTT_TLS_PUBKEY_SHA256) keep working, while clients that pin the certificate file need the new copy.
Step 6: Test on the instance
rmqtt-probe is a small MQTT client. It reads passwords from a file (or from the credentials file with --identity app) and trusts only the broker's certificate:
sudo rmqtt-probe connect --identity app
sudo rmqtt-probe connect --identity app --proto 5
sudo rmqtt-probe roundtrip --identity app --topic cloudimg-app/guide-test
sudo rmqtt-probe acl --identity app || true
sudo rmqtt-probe connect --anonymous || true
sudo rmqtt-probe plain || true
CONNACK-OK proto=4 tls=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384
CONNACK-OK proto=5 tls=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384
ROUNDTRIP OK topic=cloudimg-app/guide-test qos=1 bytes=43 proto=4 tls=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384
ACL-DENIED subscribe(#,+/#,$SYS/#,other tree,$share other tree)=0x80 publish(other tree)=disconnected own-tree=ok
REFUSED rc=4 bad-username-or-password proto=4
NOT-MQTT-PLAIN 15030300020232
The login connects with MQTT 3.1.1 and 5.0, subscribes to cloudimg-app/guide-test, publishes a message there and receives it back. acl shows the topic rules: subscriptions to #, +/#, $SYS/#, another login's tree or a shared subscription on another tree are refused (SUBACK 0x80), and a publish outside the login's own tree disconnects the client, while its own tree still works. A client without a login, with a wrong password or with an unknown user name is refused with CONNACK code 4 (MQTT 5.0: reason 0x86, bad user name or password); the broker does not say which part was wrong. Clear-text MQTT sent to 8883 gets a TLS alert, never an MQTT answer. rmqtt-probe exits non-zero on a refusal, hence || true.
Step 7: Connect a client from another machine
On the client machine, install the Mosquitto command-line clients (sudo apt-get install mosquitto-clients on Ubuntu or Debian, brew install mosquitto on macOS) and copy the certificate as in Step 5. Then put the connection settings in an options file that only you can read. mosquitto_pub and mosquitto_sub read their default options, one per line, from mosquitto_pub and mosquitto_sub files in the directory named by XDG_CONFIG_HOME (normally ~/.config), so the password is never on a command line. Keeping them in a directory of their own lets you have one per broker and login:
client-host$ umask 077; mkdir -p ~/mqtt-app
client-host$ printf -- '-h <public-ip>\n-p 8883\n--cafile %s/rmqtt.crt\n-u cloudimg-app\n' "$PWD" > ~/mqtt-app/mosquitto_pub
client-host$ ssh -i <your-key.pem> ubuntu@<public-ip> "sudo sed -n 's/^RMQTT_PASSWORD=/-P /p' /root/rmqtt-credentials.txt" >> ~/mqtt-app/mosquitto_pub
client-host$ cp ~/mqtt-app/mosquitto_pub ~/mqtt-app/mosquitto_sub
Subscribe in one terminal and publish from another:
client-host$ XDG_CONFIG_HOME=~/mqtt-app mosquitto_sub -t 'cloudimg-app/demo/#' -q 1 -v
client-host$ XDG_CONFIG_HOME=~/mqtt-app mosquitto_pub -t cloudimg-app/demo/hello -q 1 -m 'hello from mosquitto_pub'
cloudimg-app/demo/hello hello from mosquitto_pub
Use a name the certificate covers as -h: the public or private IP, an EC2 DNS name, or your own DNS name once you have added it (Step 12). Outside cloudimg-app/# the broker refuses the login's subscriptions (mosquitto_sub prints All subscription requests were denied.) and disconnects it when it publishes there (mosquitto_pub prints Error: The connection was lost.).
The same from Python with Eclipse Paho (sudo apt-get install python3-paho-mqtt, or pip install paho-mqtt):
# paho_demo.py - publish and receive through your cloudimg RMQTT broker over MQTT/TLS (paho-mqtt 1.6 or 2.x).
# Usage: python3 paho_demo.py <broker-host> <rmqtt.crt> <user> <password-file> <topic>
# The password is read from a file, never the command line; TLS trusts ONLY the broker's own certificate.
import ssl
import sys
import threading
import paho.mqtt.client as mqtt
host, cafile, user, pwfile, topic = sys.argv[1:6]
with open(pwfile) as f:
password = f.read().strip()
got = threading.Event()
try:
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
except AttributeError: # paho-mqtt 1.x
c = mqtt.Client()
c.username_pw_set(user, password)
c.tls_set(ca_certs=cafile, tls_version=ssl.PROTOCOL_TLS_CLIENT) # verify against this one certificate, host name checked
c.on_connect = lambda cl, *a: cl.subscribe(topic, qos=1)
c.on_subscribe = lambda cl, *a: cl.publish(topic, b"hello from paho", qos=1)
c.on_message = lambda cl, u, m: (print("received:", m.topic, m.payload.decode()), got.set())
c.connect(host, 8883)
c.loop_start()
ok = got.wait(15)
c.loop_stop()
c.disconnect()
sys.exit(0 if ok else 1)
client-host$ ssh -i <your-key.pem> ubuntu@<public-ip> "sudo sed -n 's/^RMQTT_PASSWORD=//p' /root/rmqtt-credentials.txt" > app.password
client-host$ python3 paho_demo.py <public-ip> rmqtt.crt cloudimg-app app.password cloudimg-app/paho-demo
received: cloudimg-app/paho-demo hello from paho
The URL form is mqtts://<public-ip>:8883. Some clients accept the login inside the URL (mqtts://cloudimg-app:<password>@...); build it inside your program from the password file rather than writing it in a configuration file or on a command line.
Step 8: Add users and topic permissions
Give each device type or application its own login rather than sharing one. rmqtt-user reads the new password from standard input (or a hidden prompt), stores only its PBKDF2-SHA256 hash and makes the login work at once, with no broker restart:
umask 077
openssl rand -hex 16 > ~/sensors.password
sudo rmqtt-user add sensors < ~/sensors.password
sudo rmqtt-user list
added sensors: publish and subscribe under sensors/# only
cloudimg-app topics=cloudimg-app/# (publish and subscribe; everything else denied)
sensors topics=sensors/# (publish and subscribe; everything else denied)
The topic rules are the same for every login: a login may publish and subscribe under its own name and nothing else, so sensors uses sensors/#. Choose login names to match the topic trees your devices use. User names are 1 to 32 characters (a-z, 0-9, _ and -); sys, admin, root, rmqtt, all and anonymous are reserved. Passwords must be 16 to 128 characters. Try the new login:
sudo rmqtt-probe acl --user sensors --password-file ~/sensors.password || true
sudo rmqtt-probe roundtrip --user sensors --password-file ~/sensors.password --topic sensors/17/temperature
ACL-DENIED subscribe(#,+/#,$SYS/#,other tree,$share other tree)=0x80 publish(other tree)=disconnected own-tree=ok
ROUNDTRIP OK topic=sensors/17/temperature qos=1 bytes=43 proto=4 tls=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384
Hand ~/sensors.password to your application's secret store, then delete the local copy. sudo rmqtt-user passwd <name> changes a password (from standard input, as for add); the old one is refused from the next login. sudo rmqtt-user remove <name> deletes a login (clients already connected with it stay connected until they disconnect; the last login cannot be removed). To remove the example user again:
sudo rmqtt-user remove sensors
shred -u ~/sensors.password
Where the topic rules live. They are in /etc/rmqtt/plugins/rmqtt-acl.toml: one rule that allows %u/# (the login's own tree) for publish and subscribe, then ["deny", "all"]. Keep the deny rule last: rules are checked in order and the first match wins, so a rule placed after it never applies, and the configuration gate refuses to start the broker if the list ends with anything else. Logins are checked only by rmqtt-authd, never by the topic rules, and the gate refuses a rule that names a superuser. After an edit, run sudo systemctl restart rmqtt (connected clients are disconnected and must reconnect).
Step 9: The broker refuses to run unsafely
rmqtt.service runs rmqtt-config-gate before every start and rmqtt-guard after it. Check the gate, and the whole broker as a client sees it, at any time:
sudo rmqtt-config-gate --unit && echo gate-ok
sudo rmqtt-selfcheck
rmqtt-config-gate: OK (unit)
gate-ok
SELFCHECK OK tls-roundtrip; acl; anonymous,wrong-password,unknown-user refused; clear-text refused, 1883/8080/6060/11883 closed
If you edit /etc/rmqtt/rmqtt.toml or a plugin file and add a clear-text, internal, WebSocket or QUIC listener, allow anonymous clients, move the gRPC server off 127.0.0.1, enable the HTTP API plugin, turn on debug logging, end the topic rules with anything but ["deny", "all"], set deny_if_error = false for the login check, or loosen the permissions of the configuration, the TLS key or the login file, the gate refuses the change and the broker does not start; journalctl -u rmqtt shows the reason. If the running broker ever listens anywhere it should not, accepts an anonymous login or runs without its firewall table, the guard stops it. If the login service stops, the broker stops with it; if it hangs, every login is refused rather than allowed.
Step 10: Why 1883, WebSockets, the HTTP API and the cluster ports are closed
RMQTT's example configuration opens a clear-text listener on 1883 and another on 11883, WebSockets on 8080 and 8443, QUIC on 9443, an HTTP management API on 6060 and its cluster gRPC server on 5363. On a cloud instance each is a way around TLS or the logins: user names, passwords and every message cross the network in clear text on 1883, and the HTTP API and the cluster port can manage the broker. This image configures exactly one network listener, MQTT over TLS on 8883, in RMQTT's own configuration rather than relying on a firewall:
- 1883 and 11883 (MQTT): not configured. Every maintained MQTT client supports TLS on 8883.
- 8080 and 8443 (WebSockets) and 9443 (QUIC): not configured. A browser application should reach MQTT through your own back end.
- 6060 (HTTP API): the
rmqtt-http-apiplugin is disabled and the gate refuses it. Manage logins withrmqtt-user. - 5363 (cluster gRPC): bound to
127.0.0.1and refused by the firewall table, because this image is a single node. - Anonymous access: refused (
allow_anonymous = false).
From another machine, even inside a security group that allows all traffic, a connection to 1883, 11883, 8080, 8443, 9443, 6060, 5363, 960, 80 or 443 is refused, and clear-text MQTT sent to 8883 gets no MQTT answer. On the instance itself:
IP=$(sudo sed -n 's/^RMQTT_PRIVATE_IP=//p' /root/rmqtt-credentials.txt)
for p in 1883 8080 8443 6060 5363 11883 8883; do nc -z -w 3 "$IP" "$p" 2>/dev/null && echo "$p open" || echo "$p closed"; done
1883 closed
8080 closed
8443 closed
6060 closed
5363 closed
11883 closed
8883 open
The broker also limits load on 8883: at most 1,000 connections from one source address and 12,000 in all, at most 10,000 sessions, a 10 second TLS handshake timeout and a 1 MB packet limit, so idle or slow clients cannot keep real clients out.
Step 11: The instance metadata block and outbound traffic
The EC2 instance metadata service (169.254.169.254) hands out the instance's IAM role credentials to any process that asks. A network service must not be able to reach it. rmqtt and rmqtt-firstboot run with the metadata addresses blocked by systemd (IPAddressDeny); rmqtt-authd may reach 127.0.0.1 only. Only rmqtt-metadata-names, which reads the instance's names for the certificate, may reach the metadata service, and it may reach nothing else:
for u in rmqtt rmqtt-authd rmqtt-firstboot rmqtt-metadata-names; do printf '%-22s deny=%s allow=%s\n' "$u" "$(systemctl show -p IPAddressDeny --value "$u")" "$(systemctl show -p IPAddressAllow --value "$u")"; done
rmqtt deny=::ffff:168.63.129.16/128 169.254.169.254/32 168.63.129.16/32 ::ffff:169.254.169.254/128 fd00:ec2::254/128 allow=
rmqtt-authd deny=::/0 0.0.0.0/0 allow=127.0.0.1/32
rmqtt-firstboot deny=169.254.169.254/32 fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 ::ffff:168.63.129.16/128 allow=
rmqtt-metadata-names deny=0.0.0.0/0 ::/0 allow=fd00:ec2::254/128 169.254.169.254/32
On top of that, the nftables table inet cloudimg_rmqtt_egress denies all outbound traffic, IPv4 and IPv6, for the broker's user rmqtt and the login service's user rmqtt-auth. Only the broker's answers to its clients and its own connection to the login service on 127.0.0.1:960 are allowed. The broker cannot reach the metadata service, the internet, your VPC or DNS, whatever its configuration says. Other users are unaffected:
IP=$(sudo sed -n 's/^RMQTT_PRIVATE_IP=//p' /root/rmqtt-credentials.txt)
for t in http://169.254.169.254/latest/meta-data/ https://1.1.1.1/ "http://$IP:22/"; do sudo -u rmqtt curl -s -m 5 -o /dev/null -w "rmqtt -> $t: %{http_code} %{errormsg}\n" "$t" || true; done
curl -s -m 5 -o /dev/null -w "ubuntu -> https://1.1.1.1/: %{http_code}\n" https://1.1.1.1/
rmqtt -> http://169.254.169.254/latest/meta-data/: 000 Failed to connect to 169.254.169.254 port 80 after 0 ms: Couldn't connect to server
rmqtt -> https://1.1.1.1/: 000 Failed to connect to 1.1.1.1 port 443 after 0 ms: Couldn't connect to server
rmqtt -> http://172.31.87.173:22/: 000 Failed to connect to 172.31.87.173 port 22 after 0 ms: Couldn't connect to server
ubuntu -> https://1.1.1.1/: 301
rmqtt-egress-guard.service loads the table before the broker starts, and the broker requires it: if the table is removed, the guard stops the broker.
Step 12: Use your own DNS name or a certificate from your CA
Point a DNS name at the instance (an Elastic IP keeps the address across stop and start), then add the name to the certificate:
sudo rmqtt-set-hostname <dns-name>
This re-issues the self-signed certificate with the same key to cover the name, updates the endpoint in /root/rmqtt-credentials.txt and restarts the broker. Copy the new certificate to clients that pin the certificate file.
To use a certificate from your CA (your own, or a public one such as Let's Encrypt), copy the chain (server certificate first) and its unencrypted PEM key to the instance, then run:
sudo rmqtt-install-cert <certificate-chain.pem> <private-key.pem> <dns-name>
Port 8883 then serves your certificate, and clients trust your CA instead of pinning this instance. The boot-time renewal never replaces an installed certificate. sudo rmqtt-set-hostname <name> goes back to a new self-signed certificate.
Logs, files and limits
- Broker log:
journalctl -u rmqtt(connections, TLS errors and refusals; never a password). Login log:journalctl -u rmqtt-authd, one line per refused login, such asrmqtt-authd: login refused user=cloudimg-app client=<client id> from=127.0.0.1. First boot:journalctl -u rmqtt-firstboot. - Configuration:
/etc/rmqtt/rmqtt.tomland/etc/rmqtt/plugins/*.toml(root:rmqtt 0640, checked by the gate on every start; changes take effect onsudo systemctl restart rmqtt). Logins:/etc/rmqtt-auth/cloudimg-users.json(hashes only; the broker cannot read it). Certificate and key:/etc/rmqtt/tls/. - Retained messages (at most 5,000, each up to 64 KB) and client sessions are kept in memory: they do not survive a broker restart or a reboot. Applications that need durable messages should republish their retained state when they reconnect.
- The broker runs as the unprivileged
rmqttuser in a systemd sandbox (no capabilities, a read-only system, a system-call filter, core dumps off). The login service runs asrmqtt-authwith only the right to bind its port. - This image runs a single RMQTT node. Clustering is not configured.
Support
cloudimg provides support for the image: launch problems, the first-boot setup, the TLS configuration and the cloudimg helpers. Contact support@cloudimg.co.uk. RMQTT itself is documented at github.com/rmqtt/rmqtt.