Deployment guide

ElasticMQ

Overview

ElasticMQ is an open-source, in-memory message queue that speaks the Amazon SQS API. Point the AWS CLI, boto3 or any AWS SDK at its endpoint with --endpoint-url and you get a fully local, SQS-compatible queue with no AWS account, no network egress and no per-message cost. It suits SQS-backed applications on a laptop, in CI pipelines and in air-gapped environments, and it lets you write fast, deterministic integration tests against real queue semantics rather than mocks.

This SecureAnyCloud image runs the pinned official ElasticMQ 1.7.1 server jar (OpenJDK 17) under systemd. ElasticMQ ships upstream with no authentication, so the image binds it to loopback only and lets nginx handle all customer-facing traffic. Port 9324, the well-known ElasticMQ port, is the drop-in SQS endpoint for your AWS SDK clients. It is deliberately unauthenticated, because SQS clients sign requests with SigV4 and cannot supply HTTP Basic Auth. Port 80 fronts the same SQS API behind a per-VM HTTP Basic Auth gate, for authenticated access from a browser or curl.

The image contains no known bootstrap credential. The Basic Auth password (user admin) is generated uniquely on the first boot of each VM.

What you get:

  • ElasticMQ 1.7.1 installed as the official fat jar, running as the elasticmq systemd service under OpenJDK 17
  • A drop-in Amazon SQS-compatible endpoint on :9324 for aws-cli, boto3 and the AWS SDKs, with ElasticMQ bound to loopback only behind nginx
  • The same SQS API on :80 behind per-VM HTTP Basic Auth (user admin), with a unique password generated on first boot
  • An unauthenticated /healthz endpoint on :80 for Azure Load Balancer health probes
  • elasticmq.service and nginx.service as enabled, active systemd units
  • In-memory storage, ElasticMQ's default, with instructions below for enabling durable queues
  • 24/7 SecureAnyCloud support

Important: storage is in-memory by default

This image uses ElasticMQ's default in-memory storage. Queues and messages live in the JVM's memory only and are lost whenever the elasticmq service restarts or the VM reboots. This keeps the image simple and dependency-free, and it suits development, CI, integration testing and demos, because the queue starts empty and deterministic every time.

If you need queues that survive restarts, ElasticMQ 1.7.1 supports optional persistence. Enable queues-storage (queue definitions) and messages-storage (messages, backed by an embedded H2 database) in /etc/elasticmq/custom.conf, following the upstream ElasticMQ documentation. Then run sudo systemctl restart elasticmq.

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting size for development and test queueing. For higher throughput, increase the JVM heap (JAVA_OPTS in the systemd unit) and the VM size.

Configure the network security group (NSG) to allow these inbound ports:

  • 22/tcp from your management network
  • 9324/tcp from the application subnets whose code sends and receives messages
  • 80/tcp if you want browser or curl access to the authenticated management endpoint
  • 443/tcp if you add TLS

ElasticMQ serves plain HTTP. The :9324 drop-in endpoint is unauthenticated by design, because SQS clients cannot supply Basic Auth. Restrict it to trusted application subnets in your NSG, and front it with TLS for production.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for ElasticMQ by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and Custom (9324) for SQS clients. Also allow HTTP (80) if you want the authenticated management endpoint.

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:elasticmq-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name elasticmq \
  --image sac1647283583153:elasticmq-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name elasticmq --port 9324 --priority 1010
az vm open-port --resource-group <your-rg> --name elasticmq --port 80 --priority 1020

Step 3 - Connect to your VM

Connect over SSH as azureuser:

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active elasticmq.service nginx.service

Both services report active. ElasticMQ serves its SQS API on the loopback address 127.0.0.1:19324 only, a port that is not reachable from the network. nginx fronts port 9324 with an unauthenticated drop-in SQS proxy for your AWS SDK clients, and port 80 with the per-VM HTTP Basic Auth gate for authenticated management access. Check the listeners:

ss -tlnH | grep -E ':80|:9324|:19324'

nginx listens on 0.0.0.0:80 and 0.0.0.0:9324. ElasticMQ listens on 127.0.0.1:19324 only, never on a public interface.

Step 5 - Retrieve your endpoint and management password

On first boot, the VM writes the SQS endpoint and the per-VM management password to a root-only file. Read it with:

sudo cat /root/elasticmq-credentials.txt

The file contains:

  • ELASTICMQ_SQS_ENDPOINT, the drop-in :9324 URL that AWS SDK clients use
  • ELASTICMQ_ADMIN_URL, the authenticated :80 endpoint
  • ELASTICMQ_USERNAME, which is admin
  • ELASTICMQ_PASSWORD, which is unique to this VM

The password is stored in /etc/nginx/.elasticmq.htpasswd only as a bcrypt hash, so no plaintext password ships in the image. Store the password somewhere safe.

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes. Request it with:

curl -s http://localhost/healthz

The endpoint returns ok. It never requires authentication, so you can use it for an Azure Load Balancer health probe.

Step 7 - Confirm authentication on the management endpoint

Because a password is set on first boot, an unauthenticated request to the :80 SQS management endpoint returns HTTP 401. This script reads the per-VM password from the credentials file and tests three cases: an unauthenticated request, a wrong password and the correct password.

PW=$(sudo grep '^ELASTICMQ_PASSWORD=' /root/elasticmq-credentials.txt | cut -d= -f2-)
echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' 'http://127.0.0.1/?Action=ListQueues&Version=2012-11-05')"
echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong-pw 'http://127.0.0.1/?Action=ListQueues&Version=2012-11-05')"
echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW 'http://127.0.0.1/?Action=ListQueues&Version=2012-11-05')"

The script prints unauth : 401, wrongpw : 401, authed : 200. Only the per-VM password reaches the SQS API on port 80. ElasticMQ itself is bound to loopback, so nginx port 80 is the only authenticated way in.

Step 8 - Create a queue and round-trip a message

The :9324 drop-in endpoint speaks the Amazon SQS wire protocol, so any SQS client works against it. These commands use plain curl against the SQS Query API to confirm the pipeline end to end on the VM itself. They create a queue, send a message and receive it back:

curl -s 'http://127.0.0.1:9324/?Action=CreateQueue&QueueName=orders&Version=2012-11-05' >/dev/null
curl -s 'http://127.0.0.1:9324/?Action=SendMessage&QueueUrl=http://127.0.0.1:9324/000000000000/orders&MessageBody=order%2342%20created&Version=2012-11-05' >/dev/null
curl -s 'http://127.0.0.1:9324/?Action=ReceiveMessage&QueueUrl=http://127.0.0.1:9324/000000000000/orders&Version=2012-11-05'

The final command returns an XML ReceiveMessageResponse containing <Body>order#42 created</Body>. This is the message you just sent, read back off the queue.

In real use, point the AWS CLI or any SDK at the endpoint from ELASTICMQ_SQS_ENDPOINT and use any dummy AWS credentials:

export AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x AWS_DEFAULT_REGION=elasticmq EP=http://<vm-ip>:9324 aws --endpoint-url $EP sqs create-queue --queue-name orders aws --endpoint-url $EP sqs send-message \
  --queue-url $EP/000000000000/orders --message-body 'order#42 created' aws --endpoint-url $EP sqs receive-message --queue-url $EP/000000000000/orders

Step 9 - Use ElasticMQ from your application

Any Amazon SQS client works. You only need to override the endpoint. With boto3:

import boto3 sqs = boto3.client( "sqs", endpoint_url="http://<vm-ip>:9324", region_name="elasticmq", aws_access_key_id="x", aws_secret_access_key="x", ) q = sqs.create_queue(QueueName="orders")["QueueUrl"] sqs.send_message(QueueUrl=q, MessageBody="order#42 created") print(sqs.receive_message(QueueUrl=q)["Messages"][0]["Body"])

The same override works for the AWS SDKs for Java, JavaScript, Go and .NET, and for frameworks such as Spring Cloud AWS. Set the SQS endpoint to http://<vm-ip>:9324 and supply any dummy credentials. Your application code is otherwise identical to code that talks to Amazon SQS, which makes ElasticMQ well suited to local development and CI.

Maintenance

  • Password: the management password is set on first boot and stored as a bcrypt entry in /etc/nginx/.elasticmq.htpasswd. To change it, run sudo htpasswd -B /etc/nginx/.elasticmq.htpasswd admin, then sudo systemctl reload nginx.
  • Storage is in-memory by default: queues and messages are lost when the elasticmq service restarts or the VM reboots. For durable queues, enable queues-storage and messages-storage in /etc/elasticmq/custom.conf as described in the upstream persistence docs, then run sudo systemctl restart elasticmq.
  • Drop-in SQS port: :9324 is intentionally unauthenticated, because SQS SDK clients sign with SigV4 and cannot supply HTTP Basic Auth. In production, restrict it in your NSG to your application subnets.
  • Endpoint address: the queue URLs ElasticMQ returns are built from node-address in /etc/elasticmq/custom.conf, which first boot sets to this VM's address. If you place the VM behind a load balancer or a different DNS name, update node-address.host there, then run sudo systemctl restart elasticmq.
  • Loopback binding: ElasticMQ is bound to 127.0.0.1:19324 in /etc/elasticmq/custom.conf, so nginx is the only path in for both the drop-in and the authenticated endpoint. Do not change the bind address to a public interface.
  • JVM sizing: the default heap is -Xms256m -Xmx512m (JAVA_OPTS in /etc/systemd/system/elasticmq.service). For higher message volume, increase the heap and the VM size, then run sudo systemctl daemon-reload && sudo systemctl restart elasticmq.
  • Restrict access and add TLS: ElasticMQ serves plain HTTP. For production, restrict access to trusted IP ranges in your NSG and front it with TLS terminating on :443, for example with certbot and your own domain.
  • Security patches: unattended-upgrades stays enabled, so the OS keeps receiving security updates automatically.

Support

SecureAnyCloud provides 24/7 support for this image. For help, email sales@secureanycloud.com.

Deploy on Azure

Launch ElasticMQ 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

Deploy on Azure