Apache TomEE
Overview
Apache TomEE is the Jakarta EE / Java EE application server from the Apache Tomcat project. The "plus" distribution this image ships bundles the full enterprise stack (JAX-RS, JPA, EJB, CDI, JMS, JSF, JTA and Bean Validation) on top of Tomcat 10.1. You can run a complete Jakarta EE application without assembling the server yourself.
The SecureAnyCloud image installs Apache TomEE 9.1.3 on OpenJDK 17 and runs it as a systemd service bound to loopback behind an nginx reverse proxy on port 80. It keeps application deployments, logs and work directories on a dedicated Azure data disk, and it generates a unique Manager password on the first boot of every VM.
What you get:
- Apache TomEE 9.1.3 "plus" (Tomcat 10.1 core,
CATALINA_HOME=/opt/tomee) on OpenJDK 17 - The Tomcat/TomEE Manager (
/manager) and host-manager (/host-manager) web consoles - nginx on
:80as a reverse proxy to the loopback TomEE connector on127.0.0.1:8080 - A per-VM admin account for the Manager, generated on first boot and recorded in a root-only file
- A dedicated Azure data disk at
/var/lib/tomee(CATALINA_BASE) for app deployments, logs and work - A small sample application deployed at
/sample/so the Manager shows a running app out of the box tomee.service+nginx.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet and subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a reasonable starting point. Size up for heavier Jakarta EE workloads. In the NSG, allow inbound 22/tcp from your management network and 80/tcp.
TomEE serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apache TomEE by SecureAnyCloud, and select Create.
On Basics, 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 HTTP (80). Review the dedicated data disk on the Disks tab. Then select Review + create, and 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:apache-tomee-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name tomee \
--image sac1647283583153:apache-tomee-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 tomee --port 80 --priority 1010Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
systemctl is-active tomee.service nginx.serviceBoth report active. TomEE listens on the loopback connector 127.0.0.1:8080 and nginx fronts it on port 80. The application deployments, logs and work directories live on the dedicated Azure data disk mounted at /var/lib/tomee.
Step 5 - Retrieve your Manager password
The TomEE Manager admin password is generated uniquely on the first boot of your VM and written to a root-only file:
sudo cat /root/tomee-credentials.txtThe file contains TOMEE_ADMIN_USERNAME (admin) and TOMEE_ADMIN_PASSWORD, along with the Manager and host-manager URLs. Store the password somewhere safe.
Step 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthIt returns ok. This endpoint never requires authentication, so you can use it for an Azure Load Balancer health probe.
Step 7 - Open the TomEE Manager
Browse to http://<vm-public-ip>/manager/html and sign in as admin with the password from Step 5. The Manager lists every deployed application and lets you start, stop, reload, undeploy and deploy WARs. The bundled /sample application is already running.
The Server Status page shows JVM memory, thread pools and connector activity.
The host-manager console at http://<vm-public-ip>/host-manager/html manages Tomcat virtual hosts.
The bundled sample application is served at http://<vm-public-ip>/sample/ and confirms the Java and server versions.
Step 8 - Verify Manager authentication from the command line
The Manager's text interface rejects a wrong password with 401 and accepts the per-VM admin password with 200. Read the password from the credentials file first, and then call the Manager.
Because the command embeds your unique password, run it interactively rather than from a script. Substitute the value of TOMEE_ADMIN_PASSWORD from Step 5 for <TOMEE_ADMIN_PASSWORD>:
curl -s -u "admin:<TOMEE_ADMIN_PASSWORD>" http://localhost/manager/text/list
The response begins with OK - Listed applications for virtual host [localhost] and lists each context, including /sample:running:...:sample. A wrong password returns 401 Unauthorized.
Step 9 - Deploy your own application
You can deploy a WAR from the Manager UI (Deploy section -> WAR file to deploy), or drop it onto the data disk and let TomEE auto-deploy it:
sudo cp /path/to/myapp.war /var/lib/tomee/webapps/Within a few seconds, TomEE expands and starts the application. It then appears in the Manager list and is served at http://<vm-public-ip>/myapp/.
The webapps directory lives on the dedicated data disk, so your deployments survive OS changes and you can resize the disk independently.
Step 10 - Confirm app data lives on the dedicated disk
TomEE's CATALINA_BASE holds the per-instance webapps, work, temp, logs and conf directories. It is stored on the dedicated Azure data disk, so it survives OS changes and you can resize it independently:
findmnt /var/lib/tomeeThe mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM.
Maintenance
- Manager users: add or rotate Manager users by editing
/var/lib/tomee/conf/tomcat-users.xmland restartingtomee.service. - Deployments: drop WARs into
/var/lib/tomee/webappsor use the Manager. Manage running apps from the Manager UI. - Logs: TomEE logs are under
/var/lib/tomee/logs(catalina.out,localhost_access_logand others) on the data disk. - Tuning: to adjust the heap size, edit
JAVA_OPTS/CATALINA_OPTSin thetomee.serviceunit (/etc/systemd/system/tomee.service). Then runsudo systemctl daemon-reload && sudo systemctl restart tomee. - TLS: TomEE serves plain HTTP on port 80. Front it with TLS (for example with certbot) and your own domain before running it in production.
- Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Deploy on Azure
Launch Apache TomEE 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 TomEE is the Jakarta EE application server from the Apache Tomcat project. The "plus" distribution this image ships bundles the full enterprise stack (JAX-RS, JPA, EJB, CDI, JMS, JSF, JTA and Bean Validation) on top of Tomcat 10.1. You can run a complete Jakarta EE application without assembling the server yourself.
The SecureAnyCloud image installs Apache TomEE on OpenJDK 17 and runs it as a systemd service bound to loopback behind an nginx reverse proxy on port 80. It keeps application deployments, configuration and logs on a dedicated EBS data volume, and it generates a unique Manager password on the first boot of every instance.
What you get:
- Apache TomEE (plus distribution) installed to
/opt/tomee, downloaded from the official Apache release and verified against its published SHA-512 checksum - OpenJDK 17 headless JVM, with heap sizing applied through the systemd unit
- nginx reverse proxy on port 80, plus an unauthenticated
/healthendpoint for load balancer and Auto Scaling health checks - A dedicated EBS data volume mounted at
/var/lib/tomeeholdingCATALINA_BASE, which contains your deployed applications, configuration, logs, work and temp directories - The TomEE Manager and host-manager consoles, authenticated and restricted to the local reverse proxy
- A deployed sample application at
/sample/so the Manager shows a running deployment immediately - A per-instance administrator password generated on first boot and written to a root-only file
Architecture and Security Model
This section explains how the pieces fit together.
- TomEE listens on
127.0.0.1:8080only. The HTTP connector inserver.xmlcarries an explicitaddress="127.0.0.1", so the application server is never directly reachable from the network, whatever your security group allows. - nginx on port 80 is the single public entry point. It proxies everything to TomEE on loopback and serves
/healthitself as a static 200, so a health check never depends on the JVM having finished starting. - The Manager and host-manager consoles require HTTP Basic authentication against
conf/tomcat-users.xml, and are additionally guarded by aRemoteAddrValvethat accepts only127.0.0.1and::1. Because requests arrive at TomEE from nginx on loopback, the consoles work through the proxy but cannot be reached by any other route. - No credential ships in the image. The AMI contains a roles-only
tomcat-users.xmlwith no<user>element at all. The administrator account is created on the first boot of each instance with a freshly generated password. CATALINA_BASEis on its own EBS volume at/var/lib/tomee, so your deployments, configuration and logs are independently resizable, snapshottable and separate from the operating system disk.
Prerequisites
Before you deploy this image, make sure you have:
- 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 and inbound port 80 (and later 443) from the networks that will reach your applications
- The AWS CLI version 2 installed locally if you plan to deploy from the command line
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 TomEE. Select the SecureAnyCloud listing, choose Select, and then choose Continue on the subscription summary.
Complete the launch wizard:
- Name: give the instance a name you will recognise, for example
tomee-prod-1. - Instance type:
m5.largeis the recommended type. TomEE is a JVM application server, so give it at least 2 vCPU and 8 GiB of memory for anything beyond evaluation. - Key pair: select your existing EC2 key pair. You need it for SSH.
- Network settings: choose your VPC and subnet. Create or select a security group that allows inbound TCP 22 from your management network and inbound TCP 80 from the networks your users will come from.
- Configure storage: the image defines a 30 GiB root volume and a 30 GiB data volume for
/var/lib/tomee. Increase the data volume now if you expect large deployments. You can also grow it later.
Choose Launch instance and wait for the instance to reach the Running state with 2/2 status checks passed.
Launch from the AWS CLI
To launch from the command line, run the following on your own machine. Substitute your own AMI ID, key pair, subnet and security group.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--subnet-id <your-subnet-id> \
--security-group-ids <your-security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=tomee-prod-1}]'Connect to your instance
Connect over SSH using the key pair you selected at launch. The login user depends on the operating system variant you launched.
Connecting to your instance
Operating system variant SSH login user
Ubuntu 24.04 LTS ubuntu
Run the following on your own machine, replacing the key path and address:
ssh -i /path/to/your-key.pem ubuntu@<public-ip>If the connection is refused, confirm that the instance has finished its status checks and that your security group allows port 22 from your current address.
Retrieve the per-instance administrator password
On the first boot of every instance, a one-shot systemd service generates a unique administrator password and writes it into the TomEE user realm. It also records the password in /root/tomee-credentials.txt with mode 0600. Read the file with sudo:
sudo cat /root/tomee-credentials.txtThe file records the console URLs, the administrator username, and the generated password. You can confirm which fields it holds without displaying the password itself:
sudo grep -oE '^[A-Z_]+=' /root/tomee-credentials.txtTOMEE_URL= TOMEE_MANAGER_URL= TOMEE_HOST_MANAGER_URL= TOMEE_ADMIN_USERNAME= TOMEE_ADMIN_PASSWORD=The administrator username is admin. Store the password in your password manager. It is unique to this instance and is not recorded anywhere else.
Verify the server is healthy
Confirm both services are running:
systemctl is-active tomee.service nginx.serviceactive activeCheck the version of TomEE and the JVM it is running on:
sudo CATALINA_HOME=/opt/tomee /opt/tomee/bin/version.sh 2>/dev/null | grep -E 'Server version|JVM Version'Server version: Apache Tomcat (TomEE)/10.1.57 (10.2.0) JVM Version: 17.0.19+10-1-24.04.2-UbuntuConfirm the listener layout. nginx is public on port 80, while TomEE is bound to loopback on 8080:
ss -tln | grep -E ':80 |:8080 'LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 511 [::]:80 [::]:* LISTEN 0 100 [::ffff:127.0.0.1]:8080 *:*The [::ffff:127.0.0.1]:8080 form is the IPv4-mapped IPv6 address the JVM binds when listening on loopback. What matters is that 8080 is not bound to 0.0.0.0.
Confirm CATALINA_BASE is on its own EBS volume:
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/tomee/dev/nvme1n1 /var/lib/tomee ext4 29.4GCheck the unauthenticated health endpoint that nginx serves directly:
curl -s -o /dev/null -w 'health endpoint: HTTP %{http_code}\n' http://127.0.0.1/healthhealth endpoint: HTTP 200Point an Elastic Load Balancing target group or an Auto Scaling health check at this endpoint.
Confirm Manager authentication
The Manager console rejects an incorrect password and accepts the generated one. You can check both cases without ever printing the password:
PW=$(sudo grep '^TOMEE_ADMIN_PASSWORD=' /root/tomee-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'wrong password -> HTTP %{http_code}\n' -u 'admin:not-the-real-password' http://127.0.0.1/manager/text/list
curl -s -o /dev/null -w 'correct password -> HTTP %{http_code}\n' -u "admin:$PW" http://127.0.0.1/manager/text/listwrong password -> HTTP 401 correct password -> HTTP 200List the deployed applications through the Manager text interface:
PW=$(sudo grep '^TOMEE_ADMIN_PASSWORD=' /root/tomee-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/manager/text/listOK - Listed applications for virtual host [localhost] /sample:running:3:sample /host-manager:running:0:host-manager /:running:0:ROOT /manager:running:2:manager /docs:running:0:docsSign in to the TomEE Manager
Open http://<public-ip>/manager/html in a browser. Your browser prompts for HTTP Basic credentials. Sign in as admin with the password from Step 4.
The Applications table lists every deployed context and lets you start, stop, reload and undeploy each one. The Deploy panel below it uploads a WAR directly from your browser. Server Information at the foot of the page confirms the TomEE version, the JVM and the operating system.
The Server Status page shows live JVM memory and connector throughput:
The JVM memory line reflects the heap settings the image applies through the systemd unit, which are an initial heap of 256 MiB and a maximum of 1024 MiB. Step 10 explains how to change them for a larger instance type.
The host-manager console at http://<public-ip>/host-manager/html manages virtual hosts and uses the same administrator credentials.
The bundled sample application
The image deploys a small Jakarta EE sample application so the Manager shows a real running deployment out of the box. Browse to http://<public-ip>/sample/:
The page renders values evaluated at request time by the server: the current time, the JVM version and the reported server identity. They confirm that JSP compilation and request handling work end to end.
The sample application is there for verification only. Once you have deployed your own application, you can remove it from the Manager's Applications table with Undeploy on the /sample row, or from the command line:
PW=$(sudo grep '^TOMEE_ADMIN_PASSWORD=' /root/tomee-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" 'http://127.0.0.1/manager/text/undeploy?path=/sample'Deploy your own application
There are three ways to deploy a WAR. Run these commands when you are ready. They change the state of your server, so they are not part of the verification steps above.
From the Manager console. Open http://<public-ip>/manager/html, scroll to WAR file to deploy, choose your .war file and select Deploy. The application appears in the Applications table and is served at the context path matching the WAR filename.
By copying the WAR onto the data volume. TomEE watches CATALINA_BASE/webapps and deploys anything dropped there. Copy the file up from your machine and move it into place:
scp -i /path/to/your-key.pem myapp.war ubuntu@<public-ip>:/tmp/
sudo install -o tomee -g tomee -m 0640 /tmp/myapp.war /var/lib/tomee/webapps/myapp.warThe application is deployed within a few seconds and served at http://<public-ip>/myapp/.
Through the Manager text interface, which is convenient from a CI pipeline:
PW=$(sudo grep '^TOMEE_ADMIN_PASSWORD=' /root/tomee-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" -T myapp.war 'http://127.0.0.1/manager/text/deploy?path=/myapp&update=true'Because /var/lib/tomee/webapps lives on the dedicated data volume, deployed applications survive an instance stop and start. An EBS snapshot of that volume alone captures them.
Tuning the JVM heap
The service unit sets an initial heap of 256 MiB and a maximum of 1024 MiB, which suits evaluation and small workloads. On a larger instance type, raise the ceiling. Edit the unit and restart:
sudo systemctl edit --full tomee.serviceChange the CATALINA_OPTS line, keeping the surrounding double quotes exactly as they are:
Environment="CATALINA_OPTS=-server -Xms1024m -Xmx4096m -Djava.security.egd=file:/dev/urandom"The quotes are required. A systemd Environment= value that is not quoted is split on whitespace and only the first token survives. That would silently discard every heap flag while the service still appears to start normally.
Then apply the change:
sudo systemctl daemon-reload
sudo systemctl restart tomee.serviceConfirm the new values on the Server Status page, or from the running process.
Configuring HTTPS
The image serves plain HTTP on port 80. Put TLS in front of it before exposing the server to production traffic.
The simplest route is a certificate from Let's Encrypt terminated at nginx. It requires a DNS name pointing at the instance and inbound port 443 open in the security group.
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d tomee.example.comCertbot edits the nginx site in place, adds the TLS listener and installs a renewal timer. The proxy configuration to TomEE is untouched, so you need no TomEE change.
If you terminate TLS at an Application Load Balancer instead, point the target group at port 80 with /health as the health check path, and leave the instance configuration as it is.
Backup and maintenance
Back up the data volume. Everything that is yours, including deployed applications, configuration and logs, lives on the EBS volume mounted at /var/lib/tomee. A snapshot of that volume captures the full application state:
aws ec2 create-snapshot \
--volume-id <data-volume-id> \
--description "TomEE application data $(date -u +%F)"Schedule these snapshots with Amazon Data Lifecycle Manager or AWS Backup for policy-driven retention.
Apply operating system updates on your normal patching schedule:
sudo apt-get update
sudo apt-get -y upgradeRead the server logs. TomEE writes to CATALINA_BASE/logs on the data volume, and the systemd journal carries the service-level record:
sudo tail -n 100 /var/lib/tomee/logs/catalina.out
sudo journalctl -u tomee.service -n 100 --no-pagerTroubleshooting
A browser request returns 502 Bad Gateway. nginx is running but TomEE is not yet accepting connections. This is normal for a few seconds after a boot or a restart while the JVM starts. If the error persists, check systemctl is-active tomee.service and read the service log.
The Manager returns 401 repeatedly. The password is unique to each instance and is read from /root/tomee-credentials.txt on the instance you are connected to. Confirm that you are reading the file on the right host and that the username is admin.
The Manager returns 403. The consoles accept requests only from the loopback reverse proxy. Reach them through http://<public-ip>/manager/html on port 80, not by connecting to port 8080 directly.
A deployed application does not appear. Confirm the WAR is owned by the tomee user and readable, and that it landed in /var/lib/tomee/webapps. Check the service log for a deployment failure.
Port 8080 is not reachable from outside. That is by design. TomEE binds to loopback only, and all external access goes through nginx on port 80.
Support
This image is published and supported by SecureAnyCloud. Our engineers provide 24/7 technical support by email and live chat, covering deployment, Apache TomEE and Tomcat configuration, application deployment troubleshooting, JVM and heap tuning, and reverse proxy and TLS setup.
Apache, Apache TomEE, TomEE, Apache Tomcat and Tomcat are trademarks of The Apache Software Foundation. All 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.
Deploy on AWS
Launch Apache TomEE on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com