Petit récapitulatif des opérations à réaliser pour la mise en production d’un serveur Tomcat 5.5 ou 6.0 (mise à jour en cours pour Tomcat 7 et 8).
Installation
Machine virtuelle
Il faut installer un JDK récent. Celui d’Oracle devrait convenir, ou éventuellement OpenJDK.
Tomcat
Même sous Linux, on installe Tomcat depuis l'archive téléchargée sur leur site. L'installation par paquet rpm, apt-get ou autre amène parfois des surprises. (cf. link:http://www.developpez.net/forums/f262/java/developpement-web-java/tomcat/[forum developpez.net])
Log4J
<strike>Je préfère largement Log4J au Java Logging API. Je fais donc le remplacement.</strike>
JULI n'est pas terrible, mais il s'est largement amélioré. Par exemple, depuis Tomcat 8, il sait écrire chaque trace sur une seule ligne, et de façon asynchrone. Je le conserve donc, en simplifiant sa link:#Traces[configuration].
Script de démarrage
<strike>Pour commencer, il peut être pratique de renseigner CATALINA_HOME, pour pouvoir l'utiliser dans la suite du script.</strike>
Tomcat est démarré avec son propre user, et surtout pas _root_. Comme j'utilise un Apache frontal, je n'ai pas besoin d'écouter sur le port 80.
Profile JVM et Mémoire
La JVM se lance avec les options par défaut, ce qui est rarement la meilleure de solutions.
-
Ajouter l’option -server
-
Ajouter les options -Xms et -Xmx
JAVA_OPTS="$JAVA_OPTS -server -Xms512m -Xmx512m"
Pour faire générer un dump de mémoire en cas de OutOfMemoryError :
JAVA_OPTS="$JAVA_OPTS -XX:-HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs"
Garbage Collector
Il n'y généralement pas d'optimisation a priori du ramasse-miettes. Son paramétrage se fait après diagnostic d'un problème.
En revanche, l'existence de collections explicites dans le code peut être une source de lenteur, il faut donc les désactiver.
JAVA_OPTS="$JAVA_OPTS -XX:+DisableExplicitGC"
JMX
<strike>En Java 5, on ajoute la propriété permettant de monitorer avec jConsole ou tout autre client JMX, comme MC4J ou jManage.</strike>
<strike>JAVA_OPTS="$JAVA_OPTS "-Dcom.sun.management.jmxremote</strike>
Si le serveur n'a pas de couche graphique, on va permettre l'accès à distance. Cet accès est sécurisé et nécessite une authentification dont les données sont stockées dans des fichiers properties, avec un fichier qui contient les couples user/password et un fichier qui associe les rôles aux users.
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1098
-Dcom.sun.management.jmxremote.access.file=$CATALINA_HOME/conf/jmx.access
-Dcom.sun.management.jmxremote.password.file=$CATALINA_HOME/conf/jmx.password"
<strike>Avec Java 6, l’accès JMX local est automatique ouvert, sans avoir à spécifier de variable supplémentaire. Cependant, en l’absence de la variable -Dcom.sun.management.jmxremote, Tomcat n’enregistrera pas ses propres MBeans ; on ne pourra donc monitorer que les données de la JVM, comme l’utilisation de la mémoire, mais pas les datasources ou connecteurs.</strike>
En conclusion, à partir de Java 5, on ajoute systématiquement la variable -Dcom.sun.management.jmxremote
.
La page JMX/Remote donne des explications plus détaillées sur cet accès.
AWT - Display
Si Tomcat est lancé sur un serveur sans display, des erreurs peuvent se produire au démarrage. Cela est du à l'utilisation de composants AWT, qui, bien que pouvant ne pas être graphiques, essaient de se rattacher à un display.
Pour éviter cette tentative de rattachement, il faut ajouter la variable -Djava.awt.headless
:
JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"
Applications fournies
Activer SSL
A partir du moment ou je veux utiliser les applications de gestion, comme le Manager, je passe par du SSL.
Sécurité du Manager
Il faut à la fois créer un user dans tomcat-users.xml et forcer l’utilisation de SSL.
Il vaut mieux stocker la version chiffrée du mot de passe :
> bin/digest.sh -a sha-512 sewatech
sewatech:6f9341ffb9...552c8a0e4
<!-- conf/tomcat-users.xml -->
<role rolename="manager" />
<user username="alexis" password="6f9341ffb9...552c8a0e4" roles="manager-gui" />
<!-- conf/server.xml -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" digest="sha-512"/>
Et pour forcer le SSL, on ajouter une user-data-constraint aux contraintes de sécurité existantes dans le fichier WEB-INF/web.xml du manager
<!-- WEB-INF/web.xml -->
<security-constraint>
<web-resource-collection>
<web-resource-name>HTML Manager interface (for humans)</web-resource-name>
<url-pattern>/html/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-gui</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
La même portion doit être ajoutée à chaque security-constraint.
Ménage
Je retire les applications inutiles :
-
docs
-
examples
-
host-manager
Pour ROOT, j’en vide le contenu pour le remplacer par une simple page index.html de redirection.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="REFRESH" content="0;URL=/myapp/">
<title>Redirecting...</title>
</head>
<body>
</body>
</html>
Applications d’admin
<strike>Je n’installe pas l’application admin, de toute façon elle ne fonctionne plus correctement dans Tomcat 6.</strike>
J’ajoute (et sécurise) les applications suivantes :
Applications métier
J’installe les applications métier + DataSource (+ Realm).
Je précompile les JSP (avec <strike>lambda probe</strike> Psi Probe)
Configuration
Ménage
Pour y voir un peu plus clair, je retire tous les commentaires dans le fichier server.xml.
Connector
SSL, mais je l'ai déjà dit. J'ouvre le connecteur AJP, pour installer Apache en frontal. Éventuellement, si AJP ne convient pas (par choix des administrateurs réseau), je crée un nouveau connecteur sur le 8082.
Chaque connecteur utilise son propre pool de thread, car je n’ai pas encore bien vu l’intérêt du pool partagé (Executor de Tomcat 6).
DataSource
Je crée les DataSources nécessaires dans GlobalNamingResources. Les jar sont placés dans libsw, déclaré comme autre répertoire de librairies (pour ne pas mélanger avec les jar d'origine).
Jasper
Désactiver le mode development
Sécurité
Utiliser les valves d’accès, au moins pour manager
Je n’active pas le SecurityManager, bien que ça pourrait être une bonne chose !
Traces
Log4J + valves de traces à la mode Apache + sewatrace