LavinMQ Ubuntu 24.04
Overview
LavinMQ is a fast, lightweight, open-source message queue and streaming server written in Crystal. It speaks AMQP 0.9.1 and is a drop-in replacement for RabbitMQ, so existing AMQP clients, tooling and the familiar HTTP management API work unchanged. It is built for high throughput and low memory use, which suits asynchronous messaging, task queues and event streaming.
This SecureAnyCloud image runs the official upstream cloudamqp/lavinmq:2.9.1 Docker image under a thin systemd wrapper. The broker binds AMQP on TCP :5672 and the built-in HTTP management console on TCP :15672. At first boot, a per-VM SecureAnyCloud administrator is created with a random password and the stock guest user is deleted entirely, so the running broker has no default login.
What you get:
- LavinMQ 2.9.1 (Apache License 2.0) from the official
cloudamqp/lavinmq:2.9.1Docker image - A single static Crystal binary, with no Erlang runtime and no Erlang cookie to manage
- A built-in web management console, enabled out of the box on
:15672 - An AMQP 0.9.1 listener on
:5672, compatible with any RabbitMQ AMQP client - The bundled
lavinmqctlandlavinmqperfCLI tools inside the container - Docker CE with the Docker Compose v2 plugin
- A container named
lavinmqwith/data/lavinmqbind-mounted for durable broker storage - A per-VM SecureAnyCloud administrator password (32 hex chars) generated at first boot
- The stock
guestuser deleted at first boot, so there is no default login - Two systemd units:
lavinmq.service(a oneshot wrapper arounddocker compose up -d) andlavinmq-firstboot.service(the per-VM admin bootstrap) - 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key, and a VNet with a subnet.
Standard_B2s (4 GB RAM) is comfortable for production AMQP traffic.
Configure the network security group (NSG) to allow inbound 22/tcp from your management CIDR. Allow 5672/tcp (AMQP) only from the client CIDRs that need to publish or consume, never from any source. AMQP and the management console are both cleartext. Reach the console through an SSH tunnel (Step 7) rather than opening 15672/tcp.
Step 1 to 3 - Deploy and connect over SSH
Deploy the image from the Azure Marketplace, then connect over SSH as azureuser:
ssh azureuser@<vm-ip>Check the service status and versions
Check the units, the container and the listening ports.
sudo systemctl is-active docker.service lavinmq.service lavinmq-firstboot.service
sudo docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
sudo ss -tln | grep -E ':5672 |:15672 'The first command reports active for all three units. docker ps shows the single lavinmq container running cloudamqp/lavinmq:2.9.1 with a healthy status. The listeners on 0.0.0.0:5672 (AMQP) and 0.0.0.0:15672 (management console) confirm that the broker is bound and ready.
Read the per-VM credentials
Print the credentials file.
sudo cat /stage/scripts/lavinmq-credentials.logNote the values of LAVINMQ_AMQP_URL, LAVINMQ_MGMT_URL, LAVINMQ_ADMIN_USER and LAVINMQ_ADMIN_PASSWORD. The file is mode 0600, owned by root, and holds the unique administrator password generated for this VM at first boot.
Verify the management API and authentication
Call the management API with and without credentials.
PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /stage/scripts/lavinmq-credentials.log | cut -d= -f2-)
echo "no credentials -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:15672/api/whoami)"
echo "sac creds -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -u "sac:$PASS" http://127.0.0.1:15672/api/whoami)" curl -s -u "sac:$PASS" http://127.0.0.1:15672/api/users | jq -r '.[].name'An unauthenticated request to the management API returns HTTP 401. The same request with the per-VM SecureAnyCloud credentials returns HTTP 200. The user list shows only SecureAnyCloud, because the stock guest account is deleted at first boot. There is no default login on the network.
Then query the overview and the current user:
PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /stage/scripts/lavinmq-credentials.log | cut -d= -f2-)
curl -s -u "sac:$PASS" http://127.0.0.1:15672/api/overview | jq '{lavinmq_version, node}'
curl -s -u "sac:$PASS" http://127.0.0.1:15672/api/whoami | jq '{name, tags}'/api/overview reports the LavinMQ version and node name. /api/whoami round-trips the management authentication and returns the SecureAnyCloud user with the administrator tag.
Log in to the management console
The AMQP listener and the management console are cleartext. The password and every message cross the network unencrypted. Allow 5672/tcp only from the client CIDRs that need it, never from any source. Do not use az vm open-port, which allows any source.
For the management console, use an SSH tunnel rather than opening 15672/tcp:
ssh -N -L 15672:127.0.0.1:15672 azureuser@<vm-public-ip>Then browse to http://127.0.0.1:15672/. If you must open a port, scope the rule to your own CIDR:
az network nsg rule create --resource-group <your-rg> --nsg-name <your-vm-nsg> \
--name amqp-5672-clients --priority 910 --direction Inbound --access Allow --protocol Tcp \
--source-address-prefixes <your-client-cidr> --destination-port-ranges 5672The console redirects to the login page. Log in as SecureAnyCloud with the password from Step 5.
Review the overview dashboard
After you log in, the Overview page shows the broker version, node uptime and live counters for connections, channels, consumers, exchanges, queues and bindings. It also charts queued messages, data rate and message rate.
On a freshly booted VM, the connection, queue and consumer counts are all zero. This is the baseline before any client connects.
Manage queues and streams
Select Queues to manage queues. The page lists every queue and provides an Add queue form, where you set the virtual host, name, durability and arguments. LavinMQ supports both classic queues and streams.
Inspect connections
Select Connections to see every AMQP client connected to the broker, with its virtual host, user, state, TLS status and protocol. Check this page first to confirm that a producer or consumer has connected.
Declare a queue and publish a message
The management API is RabbitMQ-compatible, so you can declare a queue, publish a message and consume it end to end with curl:
PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /stage/scripts/lavinmq-credentials.log | cut -d= -f2-)
curl -s -u "sac:$PASS" -H 'content-type: application/json' \
-X PUT http://127.0.0.1:15672/api/queues/%2F/hello-world -d '{"durable":true}'
curl -s -u "sac:$PASS" -H 'content-type: application/json' \
-X POST http://127.0.0.1:15672/api/exchanges/%2F/amq.default/publish \
-d '{"properties":{},"routing_key":"hello-world","payload":"Hello from sac","payload_encoding":"string"}'
curl -s -u "sac:$PASS" -H 'content-type: application/json' \
-X POST http://127.0.0.1:15672/api/queues/%2F/hello-world/get \
-d '{"count":1,"ackmode":"ack_requeue_false","encoding":"auto"}' | jq '.[0].payload'Declaring the queue returns HTTP 201, publishing returns {"routed":true}, and consuming returns the "Hello from SecureAnyCloud" payload.
The same workflow is available in the management console under Queues (declare a queue) and in each queue's publish and get message panels. The bundled lavinmqctl and lavinmqperf tools are also available with sudo docker exec lavinmq lavinmqctl <command>.
Connect from a client (Python pika example)
Publish a message from Python with the pika library.
import pika VM_IP = '<vm-ip>' PASS = '<password-from-step-5>' creds = pika.PlainCredentials('sac', PASS) conn = pika.BlockingConnection( pika.ConnectionParameters(host=VM_IP, port=5672, virtual_host='/', credentials=creds) ) ch = conn.channel() ch.queue_declare(queue='hello', durable=True) ch.basic_publish(exchange='', routing_key='hello', body='Hello World!') print('published') conn.close()Install the client with pip install pika.
The LAVINMQ_AMQP_URL from Step 5 also works directly with pika.URLParameters, kombu, aio-pika, Spring AMQP, the .NET RabbitMQ.Client and any other AMQP 0.9.1 library, because LavinMQ speaks the same protocol as RabbitMQ.
Manage users
List the broker users, and add or remove accounts, with the bundled lavinmqctl:
sudo docker exec lavinmq lavinmqctl list_usersThe list shows only the per-VM SecureAnyCloud administrator. To add an application user, run sudo docker exec lavinmq lavinmqctl add_user <name> <password>, followed by sudo docker exec lavinmq lavinmqctl set_permissions -p / <name> ".*" ".*" ".*". You can also use the Users page in the management console. Grant the administrator tag only to accounts that manage the broker.
Add TLS with a domain and Let's Encrypt
Put nginx in front of the management console and obtain a certificate. Replace the values in angle brackets with your own domain and email address:
sudo apt-get update && sudo apt-get install -y nginx python3-certbot-nginx
sudo tee /etc/nginx/sites-available/lavinmq <<'EOF' server { listen 80; server_name <your-domain>; location / { proxy_pass http://127.0.0.1:15672; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } EOF
sudo ln -sf /etc/nginx/sites-available/lavinmq /etc/nginx/sites-enabled/lavinmq
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d <your-domain> -m <your-email> --agree-tos --non-interactive --redirectCertbot adds the SSL server block and a :80 to :443 redirect, then reloads nginx. Renewal runs automatically through the certbot.timer systemd unit.
For TLS directly on the AMQP listener (5671/tcp), bind-mount a certificate into the container and enable the TLS listener in the LavinMQ configuration.
Back up the broker
Export the broker definitions (users, vhosts, exchanges, queues, bindings and policies) while the broker is running, and snapshot the data directory for message contents. Replace <backup-dir> with your own destination:
PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /stage/scripts/lavinmq-credentials.log | cut -d= -f2-)
curl -s -u "sac:$PASS" http://127.0.0.1:15672/api/definitions > <backup-dir>/lavinmq-defs.json
sudo tar czf <backup-dir>/lavinmq-data.tgz -C /data lavinmqPeriodically copy the backup directory to Azure Blob Storage (az storage blob upload-batch) for off-VM retention.
To restore, send a POST of the definitions JSON to /api/definitions while the broker is running. Then untar the data directory back to /data/lavinmq while the broker is stopped.
Read logs and troubleshoot
View the container logs, the unit logs and the broker status.
sudo docker logs lavinmq --tail 80
sudo journalctl -u lavinmq.service --no-pager -n 50
sudo journalctl -u lavinmq-firstboot.service --no-pager -n 50
sudo docker exec lavinmq lavinmqctl statusUse docker logs --tail for a snapshot of the container logs, or docker logs lavinmq -f to follow them live. The systemd unit logs cover the wrapper service and the first-boot admin bootstrap. lavinmqctl status prints the broker node state.
Security
- Per-VM administrator password. A SecureAnyCloud administrator password (32 hex chars from openssl rand) is generated at first boot.
- No default login. The stock
guestuser is deleted at first boot, so there is no default login on the network. - Loopback-only default user. LavinMQ restricts its default user to loopback by default, so
guestis never reachable over the network, even during the brief first-boot window before it is removed. - Restrict the listeners. The AMQP listener
5672/tcpand the management console15672/tcpare bound on the host. Restrict them with the NSG to known client and management CIDRs. - Small attack surface. LavinMQ is a single Crystal binary with no Erlang runtime, which reduces the attack surface compared with brokers that ship a full language VM.
- Optional TLS. You can add TLS to the management console with nginx and certbot (Step 14), and to the AMQP listener (
5671/tcp). - Durable data. Broker data persists under
/data/lavinmq, kept off the running container's writable layer.
Support
SecureAnyCloud provides 24/7/365 expert technical support. Guaranteed response within 24 hours, one hour average for critical issues. Contact sales@secureanycloud.com.
Deploy on Azure
Launch LavinMQ 2.9.1 Message Broker on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com