
Tomcat sigue siendo el contenedor de servlets más usado en servidores Linux. Este howto instala la línea actual a partir del tarball oficial de Apache, con un usuario dedicado y una unidad systemd — en Ubuntu 24.04/22.04 y Debian equivalentes.
Qué versión usar
En septiembre de 2026 Apache mantiene tres líneas estables. Para una nueva instalación, use la 11:
| Tomcat | Java mínimo | API | Situación |
|---|---|---|---|
| 11.0.25 | 17+ | Jakarta EE 11 (jakarta.*) |
actual — use esta |
| 10.1.59 | 11+ | Jakarta EE 10 (jakarta.*) |
soportada |
| 9.0.121 | 8+ | Java EE 8 (javax.*) |
EOL en 31/03/2027 |
El Tomcat 11 implementa Servlet 6.1 / JSP 4.0 y requiere Java 17 o superior. OpenJDK 25 es el LTS más reciente y funciona en esa línea. Las aplicaciones escritas para Tomcat 9 (javax.*) no se despliegan directamente en 10/11 — necesitan migrar el namespace con la herramienta oficial. Si la app aún es javax.* y no puede migrar ahora, consulte la sección de Tomcat 9 al final.
Instalando OpenJDK 25
Olvide el tarball de Oracle con cookie de licencia: en Ubuntu/Debian OpenJDK se instala con apt y recibe actualizaciones de seguridad junto con el sistema. En el servidor, la variante headless es suficiente (sin bibliotecas gráficas).
sudo apt update
sudo apt install -y openjdk-25-jdk-headless
java -version
Si el paquete openjdk-25-jdk-headless no existe en tu release, instala 21 (openjdk-21-jdk-headless) — Tomcat 11 acepta cualquier Java ≥ 17. Consulta el JAVA_HOME (la ruta cambia entre amd64 y arm64):
JAVA_HOME=$(dirname "$(dirname "$(readlink -f "$(which java)")")")
echo "$JAVA_HOME"
# exemplo amd64: /usr/lib/jvm/java-25-openjdk-amd64
Creando el grupo y el usuario tomcat
El proceso no debe ejecutarse como root. Cuenta de sistema, sin inicio de sesión y sin home adicional:
sudo groupadd --system tomcat
sudo useradd --system --no-create-home --gid tomcat
--shell /usr/sbin/nologin --home-dir /usr/local/tomcat tomcat
Descargando e instalando Tomcat 11
Descarga el tarball en el CDN oficial y comprueba el SHA-512. La versión de abajo es la 11.0.25 (12/08/2026); si ya hay una 11.0.x más nueva en tomcat.apache.org/download-11.cgi, cambia el VER.
VER=11.0.25
cd /tmp
curl -fLO "https://dlcdn.apache.org/tomcat/tomcat-11/v${VER}/bin/apache-tomcat-${VER}.tar.gz"
curl -fLO "https://downloads.apache.org/tomcat/tomcat-11/v${VER}/bin/apache-tomcat-${VER}.tar.gz.sha512"
sha512sum -c "apache-tomcat-${VER}.tar.gz.sha512"
sudo mkdir -p /usr/local/tomcat
sudo tar -xzf "apache-tomcat-${VER}.tar.gz" -C /usr/local/tomcat --strip-components=1
sudo chown -R tomcat:tomcat /usr/local/tomcat
sudo find /usr/local/tomcat -type d -exec chmod 750 {} ;
sudo find /usr/local/tomcat -type f -exec chmod 640 {} ;
sudo chmod 750 /usr/local/tomcat/bin/*.sh
La memoria de la JVM queda en el setenv.sh, que el catalina.sh carga por sí solo — así no mezclas opciones con espacios dentro de systemd:
sudo tee /usr/local/tomcat/bin/setenv.sh > /dev/null << 'EOF'
export CATALINA_OPTS="-Xms512M -Xmx1024M -server"
export JAVA_OPTS="-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"
EOF
sudo chown tomcat:tomcat /usr/local/tomcat/bin/setenv.sh
sudo chmod 750 /usr/local/tomcat/bin/setenv.sh
Ajusta -Xmx a la RAM de la máquina. 1 GB es un punto de partida razonable para un host pequeño.
Unidad systemd
Type=simple con catalina.sh run deja Java en primer plano, que es el modo que espera systemd. (Los comandos esenciales de systemd cubren start/stop/status con más detalle).
JAVA_HOME=$(dirname "$(dirname "$(readlink -f "$(which java)")")")
sudo tee /etc/systemd/system/tomcat.service > /dev/null << EOF
[Unit]
Description=Apache Tomcat 11
After=network.target
[Service]
Type=simple
User=tomcat
Group=tomcat
Environment=JAVA_HOME=${JAVA_HOME}
Environment=CATALINA_HOME=/usr/local/tomcat
Environment=CATALINA_BASE=/usr/local/tomcat
WorkingDirectory=/usr/local/tomcat
ExecStart=/usr/local/tomcat/bin/catalina.sh run
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
UMask=0007
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now tomcat
sudo systemctl status tomcat --no-pager
Comprobando que ha arrancado
ss -lntp | grep 8080
curl -I http://127.0.0.1:8080/
sudo journalctl -u tomcat -e --no-pager
La página por defecto de Tomcat debería responder 200 en http://IP:8080/. Si el puerto no se abre, el log en /usr/local/tomcat/logs/catalina.out y el journalctl muestran el motivo (JAVA_HOME incorrecto es lo más común).
Abra la 8080 en el firewall solo si se accede a Tomcat desde fuera. Con proxy inverso en la misma máquina, deje la 8080 solo en localhost:
# acesso direto (se precisar)
sudo ufw allow 8080/tcp comment 'Tomcat'
Manager (opcional)
El Manager y el Host Manager vienen desactivados para el mundo: el RemoteAddrValve en las apps manager e host-manager solo acepta localhost. Cree un usuario con contraseña fuerte — nunca admin/admin:
SENHA=$(openssl rand -base64 18)
echo "senha do manager: $SENHA"
sudo tee /usr/local/tomcat/conf/tomcat-users.xml > /dev/null << EOF
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="https://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="${SENHA}" roles="manager-gui,admin-gui"/>
</tomcat-users>
EOF
sudo chown tomcat:tomcat /usr/local/tomcat/conf/tomcat-users.xml
sudo chmod 640 /usr/local/tomcat/conf/tomcat-users.xml
sudo systemctl restart tomcat
Acceda http://127.0.0.1:8080/manager/html (Túnel SSH si el host es remoto). No exponga el Manager a Internet.
Puerto 80: nginx delante, no iptables
En 2017 este artículo redirigía 80→8080 con iptables NAT. Hoy el camino correcto es un proxy inverso: TLS, Host header y logs en nginx, Tomcat solo en 127.0.0.1:8080.
server {
listen 80;
server_name app.exemplo.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Si realmente quieres el NAT antiguo (sin nginx):
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
# persista a regra no firewall da distro (nftables/iptables-persistent/ufw),
# não no /etc/rc.local.
¿Todavía necesita Tomcat 9?
Aplicaciones antiguas en javax.* (Spring Boot 2, Java EE 8) no se ejecutan en Tomcat 11. Dos salidas:
- Migrar el WAR con el Tomcat Migration Tool for Jakarta EE y desplegar en 11.
- Quedarse en 9.0.x mientras la aplicación no migra. La línea 9.0 recibe correcciones hasta 31/03/2027; el procedimiento es el mismo que el de este artículo, cambiando la URL de descarga por la 9.0.121 en download-90.cgi (Java 8+; OpenJDK 21 también sirve).
Vídeo original (2017)
La grabación siguiente es de la instalación original (Tomcat 9 milestone). El flujo — usuario dedicado, tarball, servicio en el arranque — sigue siendo el mismo; las versiones y el Java, no.
Referencias
- Descarga de Tomcat 11
- ¿Qué versión? (tabla oficial)
- Documentación de Tomcat 11
- Fin del soporte de Tomcat 9.0.x
- Migración javax → jakarta
- OpenJDK en los repositorios de Ubuntu
Con esto tienes Tomcat 11 + OpenJDK 25 como servicio, verificado mediante checksum, sin JRE propietario y con actualización mediante apt en el lado Java. En la próxima corrección de la línea 11.0.x, basta con cambiar el tarball y repetir el chown — el JAVA_HOME e la unidad systemd siguen igual.