Streaming & Messaging AWS

LavinMQ Message Broker on AWS User Guide

| Product: LavinMQ Message Broker

Overview

This guide covers the deployment and configuration of LavinMQ on AWS using cloudimg AWS Marketplace AMIs. LavinMQ is an ultra-fast, lightweight open source message queue and streaming server written in Crystal by CloudAMQP. It speaks AMQP 0-9-1, so it is a drop-in replacement for RabbitMQ: existing RabbitMQ client libraries, tooling and the familiar management API all work unchanged. Because LavinMQ is a single static Crystal binary with no Erlang runtime, it starts in a fraction of a second and uses a fraction of the memory of comparable brokers.

The cloudimg image ships the free and open source, Apache-2.0 licensed LavinMQ, run the officially supported way as the upstream cloudamqp/lavinmq container, pinned by image digest and captured into the AMI so your instance starts in seconds. LavinMQ runs on host networking, binding the AMQP port 5672 and the HTTP management UI on port 15672 directly. Nothing here ships with a known secret: LavinMQ keeps its stock guest account restricted to the loopback interface, and on the first boot of each instance a unique cloudimg administrator with a random password is generated over the loopback management API, proven to authenticate, and the stock guest account is then deleted entirely. Backed by 24/7 cloudimg support.

LavinMQ and CloudAMQP are trademarks of their respective owners. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by any of them. It ships the free and open source Apache-2.0 licensed software, unmodified.

What is included:

  • LavinMQ 2.9.1 (the Apache-2.0 licensed AMQP 0-9-1 message broker), run as the official upstream container pinned by image digest
  • Docker Engine with the broker running on host networking, exposing AMQP on port 5672 and the built-in HTTP management UI on port 15672
  • lavinmq.service and lavinmq-firstboot.service as systemd units, enabled and active on boot, alongside docker.service
  • A per-instance cloudimg administrator with a random password, generated on first boot and written to a root-only file
  • The stock guest login deleted on first boot; no default login, no shipped secret and an empty broker on first boot
  • Ubuntu 24.04 LTS base with latest security patches applied at build time
  • 24/7 cloudimg support

Prerequisites

  • An active AWS account and an EC2 key pair in your target region
  • A subscription to the LavinMQ listing on AWS Marketplace
  • A VPC and subnet, and a security group allowing inbound 22/tcp (SSH, from your admin network), 15672/tcp (the management UI, from your admin network) and 5672/tcp (AMQP, from the networks whose clients publish and consume)

Recommended instance type: m5.large (2 vCPU, 8 GB RAM) is a sensible starting point. LavinMQ is extremely lightweight, so a general-purpose instance handles high message throughput comfortably; scale up only for very large workloads.

A note on ports: open 5672 and 15672 only to trusted networks. If you would rather not expose them at all, keep them closed in the security group and reach the broker over an SSH tunnel (shown at the end of this guide).

Connecting to your instance

Connect over SSH as the default login user for your operating system variant, using your EC2 key pair:

OS variant SSH login user
Ubuntu 24.04 LTS ubuntu
ssh -i /path/to/your-key.pem ubuntu@<public-ip>

Replace <public-ip> with your instance's public IP (or private IP if you connect over a VPN or bastion).

Retrieve your per-instance credentials

On its first boot the instance generates a unique cloudimg administrator password and writes it, together with the AMQP and management URLs, to a root-only file. Read it with:

sudo cat /root/lavinmq-credentials.txt

The file contains LAVINMQ_ADMIN_USER (always cloudimg), LAVINMQ_ADMIN_PASSWORD (unique to this instance), LAVINMQ_MGMT_URL and LAVINMQ_AMQP_URL. There is no guest login: it is deleted on first boot, so the cloudimg account is the only way in.

Verify the broker is running

Confirm the container and systemd units are up:

systemctl is-active docker lavinmq
sudo docker ps --filter name=lavinmq --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'

Query the broker's own overview through the loopback management API, authenticating as the per-instance cloudimg administrator:

PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /root/lavinmq-credentials.txt | cut -d= -f2-)
curl -s -u "cloudimg:${PASS}" http://127.0.0.1:15672/api/overview | jq '{product: .product_version, node: .node, queue_totals: .queue_totals}'

Confirm the security model: an anonymous request is rejected, and the deleted guest account cannot authenticate:

echo "no-credentials -> $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:15672/api/whoami)"
echo "deleted guest   -> $(curl -s -o /dev/null -w '%{http_code}' -u guest:guest http://127.0.0.1:15672/api/whoami)"

Both should print 401. Now prove the cloudimg administrator authenticates:

PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /root/lavinmq-credentials.txt | cut -d= -f2-)
curl -s -u "cloudimg:${PASS}" http://127.0.0.1:15672/api/whoami | jq '{name: .name, tags: .tags}'

The management UI

LavinMQ ships a built-in web management UI. Browse to it on port 15672 and sign in as cloudimg with the password from /root/lavinmq-credentials.txt:

http://<public-ip>:15672/

The LavinMQ management UI sign-in page, showing the LavinMQ logo with username and password fields and a Log in button

The Overview page shows live queued-message, data-rate and message-rate graphs for the running broker, along with counts of connections, channels, consumers, exchanges and queues.

The LavinMQ management UI overview page, signed in as the cloudimg administrator, showing live queued-message, data-rate and message-rate graphs and cluster counts

The Queues page lists every queue with its ready, unacknowledged and total message counts. From here you can create queues, publish test messages and inspect what is waiting for delivery.

The LavinMQ management UI queues page, showing durable queues with their Messages Ready and Total counts, and an Add queue form

Publish and consume a message

You can exercise the broker end-to-end from the instance itself using the RabbitMQ-compatible management API. Declare a queue, publish a message to it via the default exchange, then consume it back:

PASS=$(sudo grep '^LAVINMQ_ADMIN_PASSWORD=' /root/lavinmq-credentials.txt | cut -d= -f2-)
M=http://127.0.0.1:15672
curl -s -u "cloudimg:${PASS}" -H 'content-type: application/json' -X PUT \
  "$M/api/queues/%2F/demo.hello" -d '{"durable":true}'
curl -s -u "cloudimg:${PASS}" -H 'content-type: application/json' -X POST \
  "$M/api/exchanges/%2F/amq.default/publish" \
  -d '{"properties":{},"routing_key":"demo.hello","payload":"hello from cloudimg","payload_encoding":"string"}'
curl -s -u "cloudimg:${PASS}" -H 'content-type: application/json' -X POST \
  "$M/api/queues/%2F/demo.hello/get" \
  -d '{"count":1,"ackmode":"ack_requeue_false","encoding":"auto"}' | jq '.[0].payload'

The last command prints "hello from cloudimg" — the message published a moment earlier, consumed back off the queue.

Connect an AMQP 0-9-1 client

Any AMQP 0-9-1 client library works. Point it at amqp://cloudimg:<password>@<public-ip>:5672/. For example, with Python and pika:

import pika

params = pika.URLParameters("amqp://cloudimg:<password>@<public-ip>:5672/")
conn = pika.BlockingConnection(params)
ch = conn.channel()
ch.queue_declare(queue="orders", durable=True)
ch.basic_publish(exchange="", routing_key="orders", body="order #1001")
print("published")
conn.close()

Because LavinMQ implements AMQP 0-9-1, the same code runs unchanged against RabbitMQ — LavinMQ is a drop-in alternative.

Reach the broker over an SSH tunnel

If you keep ports 5672 and 15672 closed in your security group, forward them over SSH from your workstation:

ssh -i /path/to/your-key.pem -L 15672:127.0.0.1:15672 -L 5672:127.0.0.1:5672 ubuntu@<public-ip>

With the tunnel open, browse to http://127.0.0.1:15672/ for the management UI and point AMQP clients at amqp://cloudimg:<password>@127.0.0.1:5672/.

Managing the service

LavinMQ is managed with systemctl and runs as a Docker container under lavinmq.service:

sudo systemctl status lavinmq --no-pager
  • Restart the broker: sudo systemctl restart lavinmq
  • Stop the broker: sudo systemctl stop lavinmq
  • View broker logs: sudo docker logs lavinmq

The broker's data (definitions, queues and the message store) persists on the host at /data/lavinmq, bind-mounted into the container, so it survives restarts and reboots. The compose file lives at /opt/lavinmq/docker-compose.yml.

Enabling TLS

For production, terminate TLS in front of the broker. The simplest approach on AWS is to place a Network Load Balancer or Application Load Balancer in front of the instance with an ACM certificate, forwarding to 15672 (management) and 5672 (AMQP). Alternatively, run a reverse proxy (nginx or Caddy) on the instance for the management UI and use AMQPS with LavinMQ's own TLS configuration. cloudimg support can help you wire this up for your environment.

Security notes

  • The stock guest account is loopback-only in LavinMQ and is deleted entirely on first boot — the only account is the per-instance cloudimg administrator.
  • The cloudimg password is unique to each instance and stored in /root/lavinmq-credentials.txt (mode 0600, root only). Rotate it from the management UI (Admin → Users) or the API if you wish.
  • Open 5672 and 15672 only to the networks that need them; prefer an SSH tunnel or a load balancer with TLS for anything beyond a trusted VPC.
  • Create dedicated, least-privilege users and virtual hosts for your applications rather than sharing the administrator credential.

Support

cloudimg provides 24/7 technical support for this image by email and live chat at support@cloudimg.co.uk. We help with deployment, TLS termination, virtual hosts and user management, queue and exchange design, AMQP client integration, RabbitMQ migration, backups and scaling.