# Installation d'AREN sous Debian GNU/Linux 10 (Buster)
## Notes
Ceci n'est pas forcément la meilleure manière d'installer l'application AREN. C'est juste une documentation de comment j'ai procédé sur mon serveur que j'ai écrite pour m'en souvenir plus tard et que je partage avec vous.
L'installation décrite dans ce document à été réalisée en étant logué en tant qu'utilisateur root
Si on est logué sous un compte utilisateur normal il faut utiliser la commande `sudo su -` pour devenir root puis utiliser la commande `exit` a la fin pour revenir à la session utilisateur normal
Une autre manière de procéder est de précéder chaque commandes qui nécessites les privilèges d'administration de `sudo `
## Installation des dépendances
Mettre à jour le système
`apt-get update && apt-get dist-upgrade`
Installer postgresql, java, maven, tomcat et git si ils ne sont pas dejà installés sur le serveur :
```
apt install -y postgresql default-jdk maven tomcat9 git
```
## Installation d'AREN
Récupérer le code source d'AREN depuis github
```
cd ~
git clone https://github.com/ArenMg/aren.git aren
```
Créer un utilisateur postgresql et une base de donnée pour AREN
```
su - postgres
createuser -P aren
createdb -O aren -E UTF8 -T template0 aren_prod
exit
```
Note : La commande createuser demande de saisir un mot de passe pour le nouvel utilisateur. Notez bien le mot de passe que vous choisirez pour le reporter dans la configuration d'AREN
Copier les exemples de fichier de configuration et remplir les paramètres comme indiqué dans les commentaire contenus dans ces fichiers
```
cd ~/aren/
cp config/application.properties src/main/resources/
nano src/main/resources/application.properties
cp config/persistence.xml src/main/resources/META-INF/
nano src/main/resources/META-INF/persistence.xml
```
Compiler l'application AREN
```
cd ~/aren/
mvn clean install
```
Arréter le service tomcat et supprimer l'application installée par défaut
```
systemctl stop tomcat9
rm -rf /var/lib/tomcat9/webapps/ROOT
```
Deployer AREN à la place
(note: tuto pour déployer une webapp sous tomcat : https://www.baeldung.com/tomcat-deploy-war)
```
cd ~/aren/
cp target/aren.war /var/lib/tomcat9/webapps/ROOT.war
chown tomcat:tomcat /var/lib/tomcat9/webapps/ROOT.war
systemctl start tomcat9
systemctl status tomcat9
journalctl -feu tomcat9 # attendre que le war soit déployé (tomcat va créer une version décompressée du .war)
systemctl stop tomcat9
```
Comme indiqué dans le fichier readme, avant le premier démarrage il faut décommenter deux lignes dans le fichier persistence.xml déployé et les re-commenter après.
```
nano /var/lib/tomcat9/webapps/ROOT/WEB-INF/classes/META-INF/persistence.xml
```
Remplacer ces deux lignes :
```
<!--property name="hibernate.hbm2ddl.auto" value="drop-and-create"/-->
<!--property name="hibernate.hbm2ddl.import_files" value="META-INF/init.sql"/-->
```
Par celles là :
```
<property name="hibernate.hbm2ddl.auto" value="drop-and-create"/>
<property name="hibernate.hbm2ddl.import_files" value="META-INF/init.sql"/>
```
(En fait il suffit de supprimer `!--` au début des lignes après le `<` et de supprimer `--` à la fin des lignes avant le `>`)
Redémarer le service tomcat et vérifier si tout se passe bien
```
systemctl start tomcat9
systemctl status tomcat9
```
L'application aren doit être accessible sur le port 8080 : `http://nom-du-serveur:8080/`
**`/!\/!\/!\`**
Penser à modifier à nouveau le fichier `/var/lib/tomcat9/webapps/ROOT/WEB-INF/classes/META-INF/persistence.xml` pour recommenter les lignes comme elle l'étaient à l'origine
Sinon la base de données sera supprimée et re-crée à chaque démarrage de l'application ce qui causera une perte de toutes les données.
Par contre pour un système de test il peut être utile de garder ces paramètres pour repartir d'une base de données vierge à chaque test.
**`/!\/!\/!\`**
**Note du 05 Mai 2021** :
Sur la dernière version du code source d'AREN ces paramètre de création de la DB ont été modifié et il semble qu'il faut procéder différement (update au lieu de drop/create). Je mettrais a jour ce document lorsque le README.md d'AREN sera modifié pour expliquer la manière officielle de procéder.
## Sécurisation du serveur
Si le serveur doit être accéssible via l'internet public il est préférable de sécuriser les communication web en mettant en place un chiffrement SSL
De plus si le serveur à une adresse IP publique il faut le sécuriser un minimum en mettant en place un firewall pour bloquer tous les ports sauf ceux strictement nécessaires, mettre en place fail2ban, sécuriser les connection ssh avec une authentification par clé publique, etc...
Voir, par exemple, cette documentation réalisée par FramaSoft pour la sécuriation générale d'un serveur : https://framacloud.org/fr/auto-hebergement/securite.html
Je ne détaillerais ici que l'aspect chiffrement SSL de tomcat. Mais il est vivement recommendé d'installer au minimum un firewall (ufw par exemple) pour ne laisser ouvert vers l'extérieur que les ports réseaux strictement nécessaires (SSH, HTTP et HTTPS), de sécuriser l'accès SSH au serveur avec des clés privé/publiques et de suivre les autres recommendation du document ci-dessus.
Sur mon infrastructure de test je dispose, sur un autre serveur, d'un reverse proxy par lequel passe toutes les requetes http/https venant de l'extérieur et qui gère automatiquement le chiffrement SSL et la génération de certificats via LetsEncrypt.
En fonction de votre infrastructure la démarche à suivre pourrait être différente de ce que j'ai réalisé chez moi.
### Mettre en place un certificat auto-signé au niveau de tomcat
Note : Cette étape n'est pas strictement nécéssaire puisque c'est le reverse proxy qui fera le chiffrage SSL de tout ce qui transite sur internet avec un certificat généré par LetsEncrypt et automatiquement mis a jour. Cela permet juste, sur mon infrastructure, de chiffrer les communications entre le serveur AREN et le serveur du reverse proxy dans le cas où quelqu'un espionerait ce qui se passe sur mon réseau local. En effet, comme sur cette infrastructure ces deux composants sont sur deux machines distinctes, les communication entre le reverse proxy et le serveur tomcat peuvent être interceptée en écoutant le traffic réseau.
Cette étape est superflue dans le cas ou le reverse proxy est sur le même serveur qu'AREN. Et la sécurité est d'ailleurs meilleure en mettant les deux composants sur la même machine. En effet dans une configuration sur deux serveur avec un certificat auto-signé du coté de tomcat, nginx ne vérifie pas forcément la validité du certificat SSL utilisé par tomcat s'il n'est pas correctement configuré. Ce qui laisse la porte ouverte à des attaques de type "man in the middle".
Si le proxy nginx est installé sur le même serveur que tomcat, cette étape étant totalement inutile, aller directement à l'étape `Procédure simplifiée pour installer un reverse proxy avec nginx sur le même serveur qu'AREN`
Pour générer un certificat SLL auto signé pour tomcat :
```
mkdir -p /opt/tomcat
keytool -genkey -alias tomcat -keyalg RSA -keystore /opt/tomcat/keystore
chown tomcat:tomcat /opt/tomcat/keystore
```
Configurer SSL avec le certificat auto-signé dans le fichier server.xml de tomcat. Ouvrir ce fichier dans un éditeur :
```
nano /etc/tomcat9/server.xml
```
Et y ajouter un connecteur SSL comme suit :
```
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="150"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="/opt/tomcat/keystore" keystorePass="******"
clientAuth="false" sslProtocol="TLS"/>
```
Remplacer également le connecteur non SLL qui écoute sur le port 8080 par celui-ci qui fais une redirection sur le connecteur SSL:
```
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
```
Note : `keystorePass` est le mot de passe qui a été saisi à la génération du certificat SSL avec keytool
Redémarer le service tomcat et vérifier que tout se passe bien
```
systemctl restart tomcat9
systemctl status tomcat9
```
L'application AREN doit maintenant être accessible en SSL sur le port 8443 : `https://nom-du-serveur:8443/`
### Configurer une redirection et générer un certificat SSL signé par LetsEncrypt au niveau du reverse proxy.
Sur mon suystème de tests j'utilise Nginx Proxy Manager qui s'occupe de ca tout seul et qui se configure simplement au traver d'une interface web : https://nginxproxymanager.com/
Mais il est aussi possible d'utiliser nginx tout seul en réalisant la configuration à la main et de générer des certificats SLL avec l'utilitaire certbot de Lets Encrypt.
Voici un exemple de tutoriel qui explique les principes de base : https://openclassrooms.com/fr/courses/1733551-gerez-votre-serveur-linux-et-ses-services/5236081-mettez-en-place-un-reverse-proxy-avec-nginx
A noter qu'on est pas obligé d'installer le reverse proxy nginx sur un serveur séparé du serveur AREN comme c'est fait dans le tutoriel. Il est tout à fait possible d'installer le reverse proxy nginx sur le même serveur que l'application AREN. Et comme indiqué au chapitre précédent c'est même plus sur de faire comme ça d'un point de vue sécurité.
C'est ce que j'ai fais pour sur serveur de production pour Terre De Convergence, comme décrit dans le chapitre suivant.
### Procédure simplifiée pour installer un reverse proxy avec nginx sur le même serveur qu'AREN (sous Debian GNU/Linux) :
Installation nginx et certbot
```
# apt update && apt upgrade
# apt install nginx certbot python3-certbot-nginx -y
```
Ouverture des port HTTP et HTTPS au niveau du firewall
```
# ufw allow 'Nginx HTTP'
# ufw allow 'Nginx HTTPS'
# ufw status verbose
```
Configuration nginx
```
# nano /etc/nginx/sites-available/prog.terre-de-convergence.org
# ln -s /etc/nginx/sites-available/prog.terre-de-convergence.org /etc/nginx/sites-enabled/
# nginx -t
# systemctl reload nginx
```
Génération du certificat SSL via LetsEncrypt avec CertBot
```
# certbot --nginx
```
Voir un exemple de contenu du fichier `/etc/nginx/sites-available/prog.terre-de-convergence.org` en annexes [ci-dessous](https://md.lab12.le-led.me/s/r1iNlubKD#Un-exemple-de-fichier-de-configuration-nginx-pour-le-reverse-proxy-).
## Configuration de la mémoire utilisable par tomcat
Ajouter les options `-Xms`, `-Xmx`, `-XX:PermSize` et `-XX:MaxPermSize` sur la ligne `JAVA_OPTS` dansles fichiers `/etc/default/tomcat9` et `/etc/systemd/system/multi-user.target.wants/tomcat9.service`
Par exemple, pour le fichier `/etc/default/tomcat9` :
```
JAVA_OPTS="-Djava.awt.headless=true -Xms128m -Xmx2048m -XX:PermSize=265m -XX:MaxPermSize=1024m"
```
Et pourle fichier `/etc/systemd/system/multi-user.target.wants/tomcat9.service` :
```
Environment="JAVA_OPTS=-Djava.awt.headless=true -Xms128m -Xmx2048m -XX:PermSize=265m -XX:MaxPermSize=1024m"
```
## License
Cet article est publié sous license Creative Commons [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.fr)
Copyleft ![Copyleft](https://stratus.lab12.le-led.me/s/cxSa57Exp62ESH6/preview =18x) Douze Bé 2020/11/05
## Annexes
### Versions
Au 04/05/2021 les versions des dépendances qui étaient utilisées sur le serveur étaient :
- OS : Debian 10 (Buster) kernel linux 5.4.65
- DB : PostgreSQL 11.11
- Java : OpenJDK 11.0.11
- Build : Maven 3.6.0
- Serveur d'applications : Tomcat 9.0.31
### Mon fichier application.properties
Note : j'ai remplacé les informations personelle par des étoiles
```
# Change the production mode to alter some logging in the application
# On the client side, if set as true, the javascript and css loaded will be the minified ones
production = false
# If you are behind a reverse proxy, write here the end user root url
# Example : http://aren.my_company.fr/app
reverse-proxy = https://debats.terre-de-convergence.org
# A unique identification of you web server. Used for remote requets
# Example : My_Institution
plateform.id = terre-de-convergence
# Secret use for the creation of JWT token
authentication.jwt.secret = ********
# Issuer for the JWT token
# Example : my_domain.name
authentication.jwt.issuer = debats.terre-de-convergence.org
# Audience for the JWT token
# Example : my_domain.name
authentication.jwt.audience = debats.terre-de-convergence.org
# Validation time for the JWT tokens, in seconds
# Default is one year
authentication.jwt.validFor = 31536000
# Other configuration for JWT token, don't change if you don't know what you do
authentication.jwt.clockSkew = 10
authentication.jwt.claimNames.authorities = authorities
authentication.jwt.claimNames.refreshCount = refreshCount
authentication.jwt.claimNames.refreshLimit = refreshLimit
# SMTP configuration
# String
smtp.server = ****.********.***
# Boolean
smtp.auth = true
# Int
smtp.port = 587
# Boolean
smtp.tls = false
# String
smtp.username = ********@******.***
# String
smtp.password = ********
# ENT conexion configuration
# Example : https://cas.mon-ent-occitanie.fr/login
cas.url =
# AREN tools
# The Python scalar server
scalar.url = https://portail-aren.lirmm.fr/aren-vectors/scalar
# The python theme server
theme.url = https://portail-aren.lirmm.fr/aren-vectors/theme
# Remote tool configuration
idefix.url = http://www.jeuxdemots.org/intern_extract.php
```
### Mon fichier persistence.xml
```
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- Connection information -->
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/aren_prod"/>
<property name="hibernate.connection.username" value="aren"/>
<property name="hibernate.connection.password" value="********"/>
<property name="hibernate.default_schema" value="public"/>
<!-- SQL and DB config -->
<property name="hibernate.generate_statistics" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.use_sql_comments" value="false"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory"/>
<property name="hibernate.current_session_context_class" value="thread"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.jdbc.batch_size" value="30"/>
<property name="hibernate.jdbc.batch_versioned_data" value="true"/>
<!-- DB inititialization -->
<!--
<property name="hibernate.hbm2ddl.auto" value="drop-and-create"/>
<property name="hibernate.hbm2ddl.import_files" value="META-INF/init.sql"/>
-->
<!-- Pool configuration -->
<property name="connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/>
<property name="hibernate.c3p0.acquire_increment" value="5"/>
<property name="hibernate.c3p0.idle_test_period" value="60"/>
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.max_statements" value="50"/>
<property name="hibernate.c3p0.timeout" value="0"/>
<property name="hibernate.c3p0.acquireRetryAttempts" value="1"/>
<property name="hibernate.c3p0.acquireRetryDelay" value="250"/>
<property name="hibernate.c3p0.maxIdleTime" value="3000"/>
</properties>
</persistence-unit>
</persistence>
```
### Un exemple de fichier de configuration nginx pour le reverse proxy :
```
upstream backend_tomcat{
server 127.0.0.1:8443;
}
server {
server_name debats.terre-de-convergence.org;
location / {
include proxy_params;
proxy_pass https://backend_tomcat;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/debats.terre-de-convergence.org/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/debats.terre-de-convergence.org/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = debats.terre-de-convergence.org) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name debats.terre-de-convergence.org;
return 404; # managed by Certbot
}
```
Note : remplacer le port `8443` par `8080` dasn le bloc `upstream` et https par http sur la ligne `proxy_pass` si la mise en place d'un certificat SSL autosigné n'a pas été réalisée du coté de tomcat.
### Soucis lors de la mise a jour d'AREN
Le fichier `src/main/resources/META-INF/persistence.xml` a été ajouté sous git ce qui cause un problème de conflit avec la version paramétrée localement conformément à ce qui est indiqué dans le README.md du projet :
`Copy the persistence.xml file from the config forlder to the src/main/resources/META-INF folder. Fill the following line with the db_user, db_password and db_name previously set.`
Seul le fichier d'exemple de configuration `config/persistence.xml` devrait être sous git, pas le fichier `src/main/resources/META-INF/persistence.xml`
Même remarque pour le fichier `src/main/resources/application.properties`
```
root@euphorbe:~/aren# git log
commit 5e978d6e4f4c78b0735a7520e36cb307d74e7914 (HEAD -> main, origin/main, origin/HEAD)
Author: Henintsoa <dev.henintsoa@gmail.com>
Date: Fri Apr 16 11:34:24 2021 +0300
Aren new update
root@euphorbe:~/aren# git pull
remote: Enumerating objects: 85, done.
remote: Counting objects: 100% (85/85), done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 67 (delta 40), reused 64 (delta 37), pack-reused 0
Unpacking objects: 100% (67/67), done.
From https://github.com/ArenMg/aren
5e978d6..b068616 main -> origin/main
Updating 5e978d6..b068616
error: Your local changes to the following files would be overwritten by merge:
src/main/resources/META-INF/persistence.xml
Please commit your changes or stash them before you merge.
Aborting
root@euphorbe:~/aren#
```