This is a configuration pattern that you should try on a test server first. Paths below are for the Debian and Ubuntu package (tomcat10). Adjust them for your install.
1. Create an application folder per domain
sudo mkdir -p /var/lib/tomcat10/sites/example.org /var/lib/tomcat10/sites/example.net
sudo chown -R tomcat:tomcat /var/lib/tomcat10/sites
2. Add a Host element per domain
In /etc/tomcat10/server.xml, inside <Engine>, after the existing localhost host:
<Host name="example.org" appBase="/var/lib/tomcat10/sites/example.org"
unpackWARs="true" autoDeploy="false">
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" />
</Host>
<Host name="example.net" appBase="/var/lib/tomcat10/sites/example.net"
unpackWARs="true" autoDeploy="false">
</Host>
Use www.example.org as an alias with <Alias>www.example.org</Alias> inside the Host element.
3. Let the service write to the new folders
The Debian and Ubuntu unit restricts where Tomcat may write. Check with systemctl cat tomcat10 for lines starting with ReadWritePaths. If the new folder is not listed, add a drop-in:
sudo systemctl edit tomcat10
# add:
[Service]
ReadWritePaths=/var/lib/tomcat10/sites
Without this, unpacking a WAR fails with "Read-only file system" errors in the log.
4. Deploy each application as ROOT
sudo cp site1.war /var/lib/tomcat10/sites/example.org/ROOT.war
sudo cp site2.war /var/lib/tomcat10/sites/example.net/ROOT.war
sudo chown tomcat:tomcat /var/lib/tomcat10/sites/*/ROOT.war
sudo systemctl restart tomcat10
A WAR named ROOT.war is served at /. Any other name becomes a path such as /shop.
5. Nginx: one server block per domain
Both blocks forward to the same Tomcat and pass the original host name, because Tomcat chooses the virtual host from the Host header:
server {
server_name example.org www.example.org;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Repeat for example.net, then run certbot for each domain. See Nginx reverse proxy for a Java app.
Test and watch memory
curl -sI -H "Host: example.org" http://127.0.0.1:8080/ | head -1
curl -sI -H "Host: example.net" http://127.0.0.1:8080/ | head -1
Every application adds loaded classes, threads and caches to the same JVM. Size the heap for the total, and see how much RAM a Java app needs. If one site is much busier or less trusted than the others, give it its own server or its own Tomcat instance. A crash or a memory leak in one site otherwise brings down all of them.
Questions about multiple domains on tomcat
Can I use the same WAR name for different domains?
Yes. Each Host has its own appBase folder, so every domain can have its own ROOT.war.
Is one Tomcat or one Tomcat per site better?
One Tomcat uses less memory. Separate instances isolate crashes and let you restart one site without affecting the others.
Last updated October 29, 2026.