Apache ActiveMQ Classic on AWS User Guide
Overview
This image runs Apache ActiveMQ Classic, the long established open source message broker from the Apache Software Foundation. ActiveMQ Classic implements the Jakarta Messaging (JMS) API and speaks a broad set of wire protocols, so applications written in Java, Python, .NET, C++, Go and Node.js can all exchange messages through one broker. It supports point to point queues, publish and subscribe topics, durable subscriptions, message persistence, and a web management console for inspecting and operating destinations.
ActiveMQ Classic is a Java application and runs on OpenJDK 17, installed from the Ubuntu archive. The broker itself is installed from the official Apache binary distribution under /opt/activemq, is checksum verified during the build, runs as a dedicated unprivileged activemq service user, and is supervised by systemd as activemq.service.
The broker exposes its native OpenWire connector on port 61616, together with AMQP on 5672, STOMP on 61613 and MQTT on 1883. The Jetty web management console is deliberately bound to the loopback interface on port 8161 and is never exposed directly. An nginx reverse proxy serves the console on port 80, so the console is reached at the instance address without the raw management listener being reachable from the network. nginx also serves an unauthenticated health endpoint at /health for load balancer and monitoring checks.
Stock ActiveMQ Classic ships a well known admin / admin credential for both the web console and the broker. This image contains no such default. The build removes the administrator entry from the shipped realm files entirely, and a one shot first boot service generates a password unique to each deployed instance, applies it to both the console realm and the broker authentication plugin, and then proves the rotation worked before recording anything. Two instances launched from the same image never share a password.
The broker's KahaDB persistence store, data directory and temporary space live on a dedicated EBS data volume mounted at /var/lib/activemq, separate from the operating system disk, so message storage can be resized independently of the root volume.
ActiveMQ Classic and ActiveMQ Artemis are different products. This image is Classic, the 6.x generation of the original broker. Artemis is a separate, independently versioned broker with a different codebase and console, and cloudimg publishes it as its own listing. If you specifically need Artemis, use that listing instead.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network, inbound port 80 from the trusted networks that will reach the console, and inbound port 61616 from the networks where your messaging clients run
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Apache ActiveMQ Classic. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. ActiveMQ Classic is a Java application and benefits from memory; the dedicated data volume gives the persistence store room to grow. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group as described in the prerequisites. Do not open the console or broker ports to the public internet unless you intend them to be publicly reachable. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialisation takes approximately one to two minutes after the instance state becomes Running and the status checks pass, while the broker generates and verifies the administrator password.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Apache ActiveMQ Classic Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22, 80 and 61616 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=activemq-01}]'
The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Step 3: Connect and Retrieve the Credentials
Connect over SSH with the key pair you selected and the public IP address from step 2. The SSH login user depends on the operating system of the AMI variant you launched:
| AMI variant | SSH login user |
|---|---|
| Apache ActiveMQ Classic 6.2.7 on Ubuntu 24.04 | ubuntu |
The first boot service completes before the broker starts, so the credentials file is always in place when you log in for the first time.
sudo cat /root/activemq-credentials.txt
# Apache ActiveMQ Classic - generated on first boot by activemq-firstboot.service.
# This password is unique to this instance and was verified against the running broker
# before this file was written. Store it somewhere safe.
ACTIVEMQ_URL=http://<vm-ip>/
ACTIVEMQ_ADMIN_USER=admin
ACTIVEMQ_ADMIN_PASSWORD=<ACTIVEMQ_ADMIN_PASSWORD>
# Web console: http://<vm-ip>/ (sign in as 'admin' with the password above)
# OpenWire broker: tcp://<vm-ip>:61616 (same credential; broker auth is enabled)
# AMQP 5672 | STOMP 61613 | MQTT 1883 (enabled on the broker, not opened by the default security group)
# KahaDB persistence store + broker data: /var/lib/activemq
Copy these values somewhere secure such as a password manager or an encrypted vault, and do not commit them to source control. The same admin credential authenticates both the web console and the broker connectors.
The credentials file is owned by root and readable only by root:
sudo ls -l /root/activemq-credentials.txt
-rw------- 1 root root 680 Jul 20 08:00 /root/activemq-credentials.txt
Step 4: Verify the Broker Is Running
Both services should report active:
systemctl is-active activemq.service nginx.service
active
active
The unauthenticated health endpoint returns 200 OK and is intended for load balancer target group checks and uptime monitoring:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1/health
HTTP 200
The console rejects unauthenticated requests, and it also rejects the stock admin / admin credential that upstream ActiveMQ ships, because that credential does not exist on this image:
curl -s -o /dev/null -w 'unauthenticated: HTTP %{http_code}\n' http://127.0.0.1/admin/
curl -s -o /dev/null -w 'default credential: HTTP %{http_code}\n' -u admin:admin http://127.0.0.1/admin/
unauthenticated: HTTP 401
default credential: HTTP 401
The listening sockets show nginx on port 80, the management console bound to loopback only on 8161, and the four broker connectors:
sudo ss -tln | grep -E ':(80|8161|61616|5672|61613|1883) '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 [::ffff:127.0.0.1]:8161 *:*
LISTEN 0 128 *:5672 *:*
LISTEN 0 128 *:1883 *:*
LISTEN 0 128 *:61613 *:*
LISTEN 0 128 *:61616 *:*
Note that port 8161 is bound to 127.0.0.1 only. The management console is never directly reachable from the network; nginx on port 80 is the only path to it.
Step 5: Sign In to the Management Console
Browse to http://<instance-public-ip>/ and sign in as admin with the password from step 3. The console home view reports the broker name, version, uptime and store utilisation.

The Queues view lists every queue destination with its pending, enqueued and dequeued message counts, and offers browse, purge, pause and delete operations per destination.

The Topics view does the same for publish and subscribe destinations.

The Connections view shows the client connections currently attached to each transport connector, which is the quickest way to confirm a new client has connected successfully.

The Send view publishes a message to any queue or topic straight from the browser, which is useful for smoke testing a consumer without writing a client.

Step 6: Send and Receive a Test Message
The distribution ships a command line producer and consumer. Both require the administrator credential, because broker authentication is enabled on this image. Read the password into a shell variable rather than typing it on the command line so it does not land in your shell history:
PW=$(sudo grep '^ACTIVEMQ_ADMIN_PASSWORD=' /root/activemq-credentials.txt | cut -d= -f2-)
. /etc/default/activemq
sudo runuser -u activemq -- env ACTIVEMQ_HOME="$ACTIVEMQ_HOME" ACTIVEMQ_BASE="$ACTIVEMQ_BASE" \
ACTIVEMQ_CONF="$ACTIVEMQ_CONF" ACTIVEMQ_DATA="$ACTIVEMQ_DATA" ACTIVEMQ_TMP="$ACTIVEMQ_TMP" \
"$ACTIVEMQ_HOME/bin/activemq" producer --brokerUrl tcp://127.0.0.1:61616 \
--user admin --password "$PW" --destination queue://demo.orders --messageCount 5 \
--persistent true 2>&1 | tail -3
Consume the same five messages back off the queue:
PW=$(sudo grep '^ACTIVEMQ_ADMIN_PASSWORD=' /root/activemq-credentials.txt | cut -d= -f2-)
. /etc/default/activemq
sudo runuser -u activemq -- env ACTIVEMQ_HOME="$ACTIVEMQ_HOME" ACTIVEMQ_BASE="$ACTIVEMQ_BASE" \
ACTIVEMQ_CONF="$ACTIVEMQ_CONF" ACTIVEMQ_DATA="$ACTIVEMQ_DATA" ACTIVEMQ_TMP="$ACTIVEMQ_TMP" \
"$ACTIVEMQ_HOME/bin/activemq" consumer --brokerUrl tcp://127.0.0.1:61616 \
--user admin --password "$PW" --destination queue://demo.orders --messageCount 5 2>&1 | tail -3
After the producer runs, the queue appears in the Queues view of the console with its enqueued count, and after the consumer runs the dequeued count matches.
Step 7: Connect Your Own Clients
Point your application at the broker address using the credential from step 3. The connector endpoints are:
| Protocol | Port | Client URL |
|---|---|---|
| OpenWire (native JMS) | 61616 | tcp://<instance-public-ip>:61616 |
| AMQP 1.0 | 5672 | amqp://<instance-public-ip>:5672 |
| STOMP | 61613 | stomp://<instance-public-ip>:61613 |
| MQTT | 1883 | tcp://<instance-public-ip>:1883 |
Only port 61616 is opened by the security group recommended on the listing. If you need AMQP, STOMP or MQTT, add inbound rules for those ports to the instance's security group, restricted to the networks where your clients run. All four connectors require the admin credential; anonymous access is disabled.
A minimal Java JMS client connects like this:
ActiveMQConnectionFactory factory =
new ActiveMQConnectionFactory("tcp://<instance-public-ip>:61616");
Connection connection = factory.createConnection("admin", "<ACTIVEMQ_ADMIN_PASSWORD>");
connection.start();
For production traffic, terminate TLS in front of the broker or configure ActiveMQ's own SSL transport connectors, and restrict the broker ports to private networks. Do not send credentials over a plain connector across an untrusted network.
Step 8: Understand the Storage Layout
The persistence store sits on its own EBS volume, mounted by filesystem UUID so the mount survives device renaming across reboots and instance types:
df -h /var/lib/activemq | tail -1
/dev/nvme1n1 30G 1.3M 28G 1% /var/lib/activemq
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep -v loop
NAME SIZE TYPE MOUNTPOINT
nvme1n1 30G disk /var/lib/activemq
nvme0n1 30G disk
├─nvme0n1p1 29G part /
├─nvme0n1p14 4M part
├─nvme0n1p15 106M part /boot/efi
└─nvme0n1p16 913M part /boot
Under that mount point:
kahadbis the KahaDB persistence store, where persistent messages are writtendatais the broker data and log directorytmpis temporary spool space for large messages
To grow message storage, modify the EBS volume in the AWS console or CLI, then run sudo resize2fs /dev/nvme1n1 on the instance. The root volume is untouched by this, so you can scale the data tier independently.
Step 9: Rotate the Administrator Password
To set a new password yourself, replace the admin entry in the console realm and the broker credential, then restart the broker. Both files must carry the same value, because the console and the broker share the one credential:
AMQ_CONF=/opt/activemq/current/conf
NEW_PW='<your-new-password>'
sudo sed -i -E '/^[[:space:]]*admin[[:space:]]*=/d' "$AMQ_CONF/users.properties"
echo "admin=$NEW_PW" | sudo tee -a "$AMQ_CONF/users.properties" >/dev/null
sudo sed -i -E '/^[[:space:]]*activemq\.admin\.password[[:space:]]*=/d' "$AMQ_CONF/credentials.properties"
echo "activemq.admin.password=$NEW_PW" | sudo tee -a "$AMQ_CONF/credentials.properties" >/dev/null
sudo systemctl restart activemq.service
Update /root/activemq-credentials.txt to match so the recorded value stays accurate. Verify the new password is accepted and that the console still rejects the old one before you rely on it.
Note that credentials.properties and users.properties as shipped by Apache do not always end with a newline. Always append with a leading newline, or use the sed and echo pattern above, or the new key can be concatenated onto the previous line and silently ignored.
Step 10: Service Management and Logs
systemctl show activemq.service -p Description -p ActiveState -p SubState -p UnitFileState
Description=Apache ActiveMQ Classic message broker
ActiveState=active
SubState=running
UnitFileState=enabled
For the full unit view including the current uptime and process tree, use systemctl status activemq.service.
Useful operations:
- Restart the broker:
sudo systemctl restart activemq.service - Stop the broker:
sudo systemctl stop activemq.service - Broker log:
sudo tail -f /var/lib/activemq/data/activemq.log - systemd journal:
sudo journalctl -u activemq.service -f - Reverse proxy log:
sudo tail -f /var/log/nginx/access.log
All three services are enabled at boot:
systemctl is-enabled activemq-firstboot.service activemq.service nginx.service
enabled
enabled
enabled
Step 11: Backup and Maintenance
The broker's durable state is the KahaDB store under /var/lib/activemq/kahadb, plus the broker configuration under /opt/activemq/current/conf.
For a consistent copy of the persistence store, stop the broker first, because KahaDB is an active append only store:
sudo systemctl stop activemq.service
sudo tar -czf /var/tmp/activemq-kahadb-$(date +%F).tar.gz -C /var/lib/activemq kahadb
sudo systemctl start activemq.service
For a point in time copy without downtime, take an EBS snapshot of the data volume instead. Snapshot the configuration separately, as it lives on the root volume:
sudo tar -czf /var/tmp/activemq-conf-$(date +%F).tar.gz -C /opt/activemq/current conf
Keep the operating system patched with sudo apt-get update && sudo apt-get upgrade. Broker upgrades within the 6.x series are done by extracting the new Apache distribution alongside the existing one, repointing the /opt/activemq/current symlink, carrying your conf changes across, and restarting the service. Review the Apache release notes before upgrading, and take a snapshot of the data volume first.
How First Boot Secures the Instance
The activemq-firstboot.service one shot unit runs once, before the broker starts. It generates a random 24 character password, writes it into the console realm file and into the broker credential file, and then verifies the result against a broker it starts itself:
- The console must reject an unauthenticated request
- The console must reject the stock
admin/admincredential - The console must accept the newly generated password
- A message must be produced and consumed successfully using the new credential
- The broker must reject the stock
admin/admincredential
Only when all five checks pass does the service write /root/activemq-credentials.txt, install the login banner, and create its completion sentinel at /var/lib/cloudimg/activemq-firstboot.done. If any check fails it exits without writing the sentinel, so the rotation runs again on the next boot; because activemq.service requires the first boot unit, the broker never starts with an unverified credential.
You can confirm this ran on your instance:
sudo journalctl -u activemq-firstboot.service --no-pager | grep -E 'PROOF|proofs passed' | sed 's/^.*activemq-firstboot: //'
PROOF 1/5 - console must reject an unauthenticated request
PROOF 2/5 - console must reject the stock default admin/admin
PROOF 3/5 - console must accept the per-instance password
PROOF 4/5 - broker must accept a produce+consume round trip with the new password
PROOF 5/5 - broker must reject the stock default admin/admin
All 5 rotation proofs passed
Troubleshooting
The console returns 502 Bad Gateway. The broker is still starting. A JVM broker typically needs one to two minutes on first boot. Check sudo systemctl status activemq.service and sudo tail -50 /var/lib/activemq/data/activemq.log.
The broker will not start and the log mentions an unresolved placeholder. The activemq.admin.password key is missing from conf/credentials.properties. This is the fail closed state: the broker deliberately refuses to run without a credential. Re-run first boot with sudo rm -f /var/lib/cloudimg/activemq-firstboot.done && sudo systemctl restart activemq-firstboot.service, then start the broker.
A client is rejected with a security exception. Broker authentication is enabled and anonymous access is disabled. Supply the admin username and the password from /root/activemq-credentials.txt in your client's connection factory.
The console is unreachable from a browser but works with curl on the instance. The security group is not allowing inbound port 80 from your network. The console is bound to loopback by design and reached only through nginx.
A queue is filling up and never drains. No consumer is attached. Check the Connections view in the console, and confirm your consumer is connecting to the right destination name; queue names are case sensitive.
Support
cloudimg provides 24/7 technical support for this image by email and live chat.
- Email: support@cloudimg.co.uk
- Live chat: available 24/7 on cloudimg.co.uk
Our engineers can help with broker deployment, connector and protocol configuration, queue and topic design, persistence tuning, network of brokers topologies, upgrades, and troubleshooting. Critical issues receive a one hour average response.
Apache, ActiveMQ and Apache ActiveMQ are trademarks of the Apache Software Foundation. All other product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.