Apache JMeter
Overview
Apache JMeter is the de-facto open-source tool for load and performance testing. The SecureAnyCloud image ships JMeter as a headless server appliance. JMeter's GUI is a desktop Swing application and is not installed for interactive use, so you work through non-GUI command-line test execution and the JMeter distributed-mode remote engine.
The distributed-mode engine listens on 127.0.0.1 only, and the RMI ports are never opened to the internet. Run headless tests locally on the VM, or attach a remote JMeter controller over an SSH tunnel, using the per-VM keystore as the trust boundary.
What you get:
- Apache JMeter 5.6.3 (Apache-2.0) from the official Apache binary distribution at
/opt/jmeter - Headless (non-GUI) test execution:
jmeter -n -t plan.jmx -l results.jtl - The distributed-mode remote engine
jmeter-serverrunning as asystemdservice (jmeter-server.service) under a dedicated unprivilegedjmeteruser - OpenJDK 17 (Ubuntu 24.04 main) as the JVM runtime
- RMI registry on
127.0.0.1:1099and the server engine port on127.0.0.1:1100, both loopback-only, with RMI SSL enabled against a per-VM keystore generated on first boot - A bundled sample test plan at
/opt/jmeter/sample.jmx - HTML dashboard report generation from
.jtlresults - Test plans, results and reports on a dedicated 30 GiB Azure data disk at
/var/lib/jmeter - 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B4ms (4 vCPU / 16 GiB RAM) is a good starting point for the JVM-based engine.
Configure the network security group (NSG) to allow inbound 22/tcp from your management network. You need no inbound application ports, because tests run locally or you reach the remote engine over the SSH tunnel.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apache JMeter 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) only. Then select Review + create and Create.
Step 2 - Deploy from the Azure CLI
Alternatively, deploy from the command line:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:apache-jmeter-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name jmeter \
--image sac1647283583153:apache-jmeter-ubuntu-24-04:default:latest \
--size Standard_B4ms \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku StandardStep 3 - Connect to your VM
Connect to the VM over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Confirm JMeter is installed and the engine is running
Check the JMeter version and the engine service:
/opt/jmeter/bin/jmeter --version 2>/dev/null | grep -v WARN | head -6 systemctl is-active jmeter-server.serviceYou should see the JMeter 5.6.3 banner and active:
_ ____ _ ____ _ _ _____ _ __ __ _____ _____ _____ ____ / \
| _ \
/ \
/ ___| | | | ____| | | \/ | ____|_ _| ____| _ \
/ _ \
| |_) / _ \| | | |_| | _| _ | | |\/| | _| | | | _| | |_) | / ___ \| __/ ___ \
|___| _ | |___ | |_| | | | | |___ | | | |___| _ < /_/ \_\_| /_/ \_\____|_| |_|_____| \___/|_| |_|_____| |_| |_____|_| \_\ 5.6.3 activeStep 5 - Confirm the distributed-mode engine binds to loopback only
The distributed-mode jmeter-server engine listens on the RMI registry port 1099 and the server engine port 1100, both bound to loopback. Verify the bindings:
ss -tln | grep -E ':1099|:1100'LISTEN 0 50 [::ffff:127.0.0.1]:1100 *:* LISTEN 0 50 [::ffff:127.0.0.1]:1099 *:*Both ports are bound to 127.0.0.1, and an nftables guard drops any non-loopback traffic to them. They are never exposed to the internet.
Step 6 - Read the per-VM endpoint notes
On first boot, each VM writes its endpoint details to an information file. It includes the RMI endpoint, the per-VM RMI SSL keystore path, and the per-VM keystore password that you use to attach a remote controller:
cat /var/lib/sac/data/apache-jmeter-endpoints.notesThe file records JMETER_HOME, the loopback RMI endpoint, the keystore path, the per-VM JMETER_RMI_KEYSTORE_PASSWORD, the public IP, and the SSH-tunnel guidance.
Step 7 - Review the bundled sample test plan
A sample test plan ships at /opt/jmeter/sample.jmx. It contains a 5-thread x 20-loop thread group with a Summary Report listener. Confirm that it is present:
ls -l /opt/jmeter/sample.jmxStep 8 - Run a headless (non-GUI) test
Run the bundled sample plan headless with jmeter -n and write the results to a .jtl file. The run prints a live summary and an end-of-run line:
sudo -u jmeter /opt/jmeter/bin/jmeter -n -t /opt/jmeter/sample.jmx -l /var/lib/jmeter/results/run.jtl 2>/dev/null | grep -vE 'WARN Status' | tail -8You should see the run reach ... end of run with the read and write counts and zero errors:
Starting standalone test @ 2026 Jun 24 21:49:29 UTC (1782337769902) Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445 summary + 1 in 00:00:00 = 6.2/s Avg: 122 Min: 122 Max: 122 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0 summary + 99 in 00:00:03 = 29.2/s Avg: 141 Min: 11 Max: 261 Err: 0 (0.00%) Active: 0 Started: 5 Finished: 5 summary = 100 in 00:00:04 = 28.2/s Avg: 141 Min: 11 Max: 261 Err: 0 (0.00%) Tidying up ... @ 2026 Jun 24 21:49:33 UTC (1782337773532) ... end of runStep 9 - Generate an HTML dashboard report
Generate a JMeter HTML dashboard report from the .jtl results with jmeter -g. Then list the report directory. It belongs to the jmeter user, so list it with sudo:
sudo -u jmeter /opt/jmeter/bin/jmeter -g /var/lib/jmeter/results/run.jtl -o /var/lib/jmeter/reports/run 2>/dev/null | grep -iE 'report|dashboard' | head -2 sudo ls -1 /var/lib/jmeter/reports/runThe report directory contains index.html, the content graphs, and statistics.json:
content index.html sbadmin2-1.0.7 statistics.jsonOpen index.html in a browser to see the response-time, throughput and over-time dashboards. Copy the report directory off the VM, or serve it over an SSH tunnel.
Step 10 - Run your own test plan
Copy your own .jmx plan to the data disk and run it headless, writing results and generating a report:
# Copy your plan to the VM (from your workstation): scp my-plan.jmx azureuser@<vm-public-ip>:/var/lib/jmeter/test-plans/
# On the VM:
sudo -u jmeter /opt/jmeter/bin/jmeter -n -t /var/lib/jmeter/test-plans/my-plan.jmx -l /var/lib/jmeter/results/my-run.jtl
sudo -u jmeter /opt/jmeter/bin/jmeter -g /var/lib/jmeter/results/my-run.jtl -o /var/lib/jmeter/reports/my-runStep 11 - Drive this VM as a remote engine (distributed mode)
The jmeter-server engine is the remote half of JMeter's distributed (master/worker) mode. The RMI endpoint listens on 127.0.0.1:1099 only and is secured with RMI SSL against the per-VM keystore at /var/lib/jmeter/rmi_keystore.jks.
To drive this VM from a controller, open an SSH tunnel, copy the keystore to the controller, point the controller's jmeter.properties at it, and target the tunnelled endpoint:
# On your workstation:
ssh -L 1099:127.0.0.1:1099 azureuser@<vm-public-ip> scp azureuser@<vm-public-ip>:/var/lib/jmeter/rmi_keystore.jks ./rmi_keystore.jks
# Then on the controller (with the keystore + per-VM password configured): jmeter -n -t my-plan.jmx -R 127.0.0.1:1099 -l results.jtlNever expose 1099 or 1100 to the internet. The per-VM keystore and loopback binding are the security boundary.
Maintenance
- Data: Test plans,
.jtlresults and HTML reports live on the dedicated data disk at/var/lib/jmeter, so they survive reboots and you can resize the volume independently. - Engine: The distributed-mode remote engine runs as
jmeter-server.service. Restart it withsudo systemctl restart jmeter-server.service. - Tuning: Edit
/opt/jmeter/bin/user.propertiesfor engine and RMI tuning, then restart the service. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
- Security boundary: The RMI registry and server engine ports bind to loopback only, with RMI SSL against a per-VM keystore. Keep
1099/1100off the public internet and reach the remote engine over the SSH tunnel.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Apache JMeter and the Apache feather logo are trademarks of The Apache Software Foundation. This image is provided by SecureAnyCloud and is not affiliated with or endorsed by The Apache Software Foundation.
Deploy on Azure
Launch Apache JMeter 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
Overview
Apache JMeter is the de-facto open-source tool for load and performance testing of web applications, APIs, databases and other services. The SecureAnyCloud image ships JMeter as a headless server appliance. JMeter's GUI is a desktop Swing application and is not installed for interactive use, so you work through non-GUI command-line test execution and the JMeter distributed-mode remote engine.
The distributed-mode engine listens on 127.0.0.1 only, and the RMI ports are never opened to the internet. Run headless tests locally on the instance, or attach a remote JMeter controller over an SSH tunnel, using the per-instance keystore as the trust boundary.
What you get:
- Apache JMeter 5.6.3 (Apache-2.0) from the official Apache binary distribution at
/opt/jmeter - Headless (non-GUI) test execution:
jmeter -n -t plan.jmx -l results.jtl - The distributed-mode remote engine
jmeter-serverrunning as asystemdservice (jmeter-server.service) under a dedicated unprivilegedjmeteruser - OpenJDK 17 (Ubuntu 24.04 main) as the JVM runtime
- RMI registry on
127.0.0.1:1099and the server engine port on127.0.0.1:1100, both loopback-only, with RMI SSL enabled against a per-instance keystore generated on first boot - A bundled sample test plan at
/opt/jmeter/sample.jmx - HTML dashboard report generation from
.jtlresults - Test plans, results and reports on a dedicated 30 GiB EBS data volume at
/var/lib/jmeter - 24/7 SecureAnyCloud support
Prerequisites
You need an active AWS account, an EC2 key pair, and a VPC with a subnet in the target region.
m5.large (2 vCPU / 8 GiB RAM) is a good starting point for the JVM-based engine. For high-concurrency or distributed load generation, use larger compute-optimized instances (c5 or c6i).
Configure the security group to allow inbound 22/tcp from your management network. You need no inbound application ports, because tests run locally on the instance or you reach the remote engine over the SSH tunnel.
Connecting to your instance
Connect over SSH on port 22 as the default login user for your AMI variant:
OS variant SSH login user Connect
Ubuntu 24.04 LTS ubuntu ssh ubuntu@<instance-public-ip>
Step 1 - Deploy from the AWS Marketplace
Sign in to AWS Marketplace, search for Apache JMeter by SecureAnyCloud, and choose Continue to Subscribe. Accept the terms, then choose Continue to Configuration. Pick the region and AMI variant, and choose Continue to Launch.
Under Launch this software, choose your instance type (m5.large is a good start), your VPC and subnet, an EC2 key pair, and a security group that allows SSH (22) from your management network only. Then choose Launch.
Step 2 - Deploy from the AWS CLI
Alternatively, deploy from the command line:
aws ec2 run-instances \
--image-id <marketplace-ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <sg-allowing-22> \
--subnet-id <your-subnet> \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=20,VolumeType=gp3}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=jmeter}]'Step 3 - Connect to your instance
Connect to the instance over SSH:
ssh ubuntu@<instance-public-ip>Step 4 - Confirm JMeter is installed and the engine is running
Confirm the JMeter binaries, the running distributed-mode engine, and that the RMI ports are bound to loopback only:
sudo -u jmeter env JMETER_HOME=/opt/jmeter /opt/jmeter/bin/jmeter --version 2>/dev/null | tail -8 systemctl is-active jmeter-server.service ss -tln | grep -E ':1099|:1100'
sudo nft list table inet jmeter_guardYou should see the JMeter 5.6.3 banner, active, both RMI ports listening on 127.0.0.1, and the nftables guard dropping any non-loopback ingress to 1099/1100:
... 5.6.3 Copyright (c) 1999-2024 The Apache Software Foundation active LISTEN 0 50 [::ffff:127.0.0.1]:1100 *:* LISTEN 0 50 [::ffff:127.0.0.1]:1099 *:* iif "lo" accept iifname != "lo" tcp dport { 1099, 1100 } dropStep 5 - Review the per-instance endpoint notes
On first boot, the image generates a fresh per-instance RMI SSL keystore and writes an endpoint notes file. Read it:
sudo cat /var/lib/sac/data/apache-jmeter-endpoints.notesThe file records JMETER_HOME, the loopback RMI endpoint, the keystore path, the per-instance JMETER_RMI_KEYSTORE_PASSWORD, the public IP, and the SSH-tunnel guidance. Treat the keystore and its password as connection material, because they are the trust boundary for distributed mode.
Step 6 - Review the bundled sample test plan
A sample test plan ships at /opt/jmeter/sample.jmx. It contains a 5-thread x 20-loop thread group with a Summary Report listener. Confirm that it is present:
ls -l /opt/jmeter/sample.jmxStep 7 - Run a headless (non-GUI) test
Run the bundled sample plan headless with jmeter -n and write the results to a .jtl file. The run prints a live summary and an end-of-run line:
sudo -u jmeter /opt/jmeter/bin/jmeter -n -t /opt/jmeter/sample.jmx -l /var/lib/jmeter/results/run.jtl 2>/dev/null | grep -vE 'WARN Status' | tail -8You should see the run reach ... end of run with 100 samples and zero errors:
Created the tree successfully using /opt/jmeter/sample.jmx Starting standalone test @ 2026 Jul 21 11:20:04 UTC (1784632804996) summary + 1 in 00:00:00 = 4.6/s Avg: 133 Min: 133 Max: 133 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0 summary + 99 in 00:00:04 = 27.0/s Avg: 141 Min: 11 Max: 261 Err: 0 (0.00%) Active: 0 Started: 5 Finished: 5 summary = 100 in 00:00:04 = 25.8/s Avg: 141 Min: 11 Max: 261 Err: 0 (0.00%) Tidying up ... @ 2026 Jul 21 11:20:09 UTC (1784632809023) ... end of runStep 8 - Generate an HTML dashboard report
Generate a JMeter HTML dashboard report from the .jtl results with jmeter -g, then list the report directory:
sudo -u jmeter /opt/jmeter/bin/jmeter -g /var/lib/jmeter/results/run.jtl -o /var/lib/jmeter/reports/run 2>/dev/null | tail -2 ls -1 /var/lib/jmeter/reports/runThe report directory contains index.html, the content graphs, and statistics.json:
content index.html sbadmin2-1.0.7 statistics.jsonOpen index.html in a browser to see the APDEX score, the pass/fail requests summary, and the response-time, throughput and over-time dashboards. Copy the report directory off the instance, or serve it over an SSH tunnel:
Step 9 - Run your own test plan
Copy your own .jmx plan to the data volume and run it headless, writing results and generating a report:
# Copy your plan to the instance (from your workstation): scp my-plan.jmx ubuntu@<instance-public-ip>:/tmp/my-plan.jmx
# On the instance:
sudo install -o jmeter -g jmeter -m 0644 /tmp/my-plan.jmx /var/lib/jmeter/test-plans/my-plan.jmx
sudo -u jmeter /opt/jmeter/bin/jmeter -n -t /var/lib/jmeter/test-plans/my-plan.jmx -l /var/lib/jmeter/results/my-run.jtl
sudo -u jmeter /opt/jmeter/bin/jmeter -g /var/lib/jmeter/results/my-run.jtl -o /var/lib/jmeter/reports/my-runStep 10 - Drive this instance as a remote engine (distributed mode)
The jmeter-server engine is the remote half of JMeter's distributed (controller/worker) mode. The RMI endpoint listens on 127.0.0.1:1099 only and is secured with RMI SSL against the per-instance keystore at /var/lib/jmeter/rmi_keystore.jks.
To drive this instance from a controller, open an SSH tunnel, copy the keystore to the controller, point the controller's jmeter.properties at it, and target the tunnelled endpoint:
# On your workstation:
ssh -L 1099:127.0.0.1:1099 ubuntu@<instance-public-ip>
sudo scp ubuntu@<instance-public-ip>:/var/lib/jmeter/rmi_keystore.jks ./rmi_keystore.jks
# Then on the controller (with the keystore + per-instance password configured): jmeter -n -t my-plan.jmx -R 127.0.0.1:1099 -l results.jtlNever expose 1099 or 1100 to the internet. The per-instance keystore and loopback binding are the security boundary.
To generate distributed load at scale, launch a fleet of instances from this AMI and drive them all from a single controller.
Maintenance
- Data: Test plans,
.jtlresults and HTML reports live on the dedicated EBS data volume at/var/lib/jmeter, so they survive reboots and you can resize the volume independently. Use EBS snapshots to back it up. - Engine: The distributed-mode remote engine runs as
jmeter-server.service. Restart it withsudo systemctl restart jmeter-server.service. - Tuning: Edit
/opt/jmeter/bin/user.propertiesfor engine and RMI tuning, then restart the service. - Security patches: The OS continues to receive security updates. Apply them with
sudo apt-get update && sudo apt-get upgrade. - Security boundary: The RMI registry and server engine ports bind to loopback only, with RMI SSL against a per-instance keystore. Keep
1099/1100off the public internet and reach the remote engine over the SSH tunnel.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Apache JMeter and the Apache feather logo are trademarks of The Apache Software Foundation. This image is provided by SecureAnyCloud and is not affiliated with or endorsed by The Apache Software Foundation.
Deploy on AWS
Launch Apache JMeter on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com