xmpp/README.md

756 lines
18 KiB
Markdown

# Service XMPP
Service de messagerie instantanée du chaton de Libre en communs, basé sur [XMPP](https://xmpp.org) et le serveur [ejabberd](https://ejabberd.im).
Responsable: Adrien Bourmault (@neox)
Le contenu de ce répertoire est publié sous licence libre GNU AGPL3+.
# Installation
## Prérequis
On aura besoin de quelques paquets de base :
```
sudo apt install postgresql erlang-p1-pgsql erlang
sudo apt install certbot
```
On utilise pour `ejabberd` le dépôt de paquets de ProcessOne. Il faut commencer par déployer la liste de sources et la clé de signature :
```
curl -o /etc/apt/sources.list.d/ejabberd.list https://repo.process-one.net/ejabberd.list
curl -o /etc/apt/trusted.gpg.d/ejabberd.gpg https://repo.process-one.net/ejabberd.gpg
```
On crée un utilisateur pour la base de données postgres :
```
sudo -u postgres createuser -P ejabberd
sudo -u postgres createdb -O ejabberd ejabberd
```
## Installation du serveur XMPP ejabberd
On installe le paquet `ejabberd` des dépôts de Debian stable :
```
sudo apt install ejabberd
```
On initialise la base de données avec le schéma récupéré dans les fichiers installés par le paquet :
```
psql -U ejabberd ejabberd < /usr/share/ejabberd/sql/pg.new.sql
```
On édite ensuite la configuration dans `/etc/ejabberd/ejabberd.yml`.
Afin de pouvoir réaliser des statistiques sur l'utilisation des appels audio/vidéo, on renforce la verbosité tout en masquant le maximum de données privées :
```
# loglevel: Verbosity of log files generated by ejabberd
loglevel: info
hide_sensitive_log_data: true
```
On paramètre les domaines couverts par le service :
```
hosts:
- chalec.org
```
On indique l'emplacement des certificats (préalablement créés avec certbot) et on désactive le système interne de demande de certificat :
```
certfiles:
- /etc/letsencrypt/live/xmpp.chalec.org/fullchain.pem
- /etc/letsencrypt/live/xmpp.chalec.org/privkey.pem
- /etc/letsencrypt/live/chalec.org/fullchain.pem
- /etc/letsencrypt/live/chalec.org/privkey.pem
acme:
auto: false
```
On peut alors paramétrer les différents modules du service XMPP, c'est à dire le C2S, le S2S, TURN/STUN pour les appels audio/vidéo :
```
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: true
protocol_options: 'TLS_OPTIONS'
-
port: 5223
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
protocol_options: 'TLS_OPTIONS'
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
-
port: 5444
ip: "::"
module: ejabberd_http
tls: true
protocol_options: 'TLS_OPTIONS'
request_handlers:
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
custom_headers:
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": "OPTIONS, HEAD, GET, PUT"
"Access-Control-Allow-Headers": "Authorization"
"Access-Control-Allow-Credentials": "true"
-
port: 5280
ip: "::"
module: ejabberd_http
tls: true
protocol_options: 'TLS_OPTIONS'
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
# PUBLIC TURN
-
port: 3475
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
auth_type: anonymous
#auth_realm:
turn_ipv4_address: PUBLIC_IPV4
turn_ipv6_address: PUBLIC_IPV6
-
port: 3475
ip: "::"
transport: tcp
module: ejabberd_stun
use_turn: true
auth_type: anonymous
#auth_realm:
turn_ipv4_address: PUBLIC_IPV4
turn_ipv6_address: PUBLIC_IPV6
-
port: 3478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
#auth_type: anonymous
auth_realm: chalec.org
turn_ipv4_address: PUBLIC_IPV4
turn_ipv6_address: PUBLIC_IPV6
-
port: 3478
ip: "::"
transport: tcp
module: ejabberd_stun
use_turn: true
#auth_type: anonymous
auth_realm: chalec.org
turn_ipv4_address: PUBLIC_IPV4
turn_ipv6_address: PUBLIC_IPV6
-
port: 8448 # Matrix federation
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
"/_matrix": mod_matrix_gw
```
On active SCRAM pour les mots de passes utilisateurs et STARTTLS pour les connexions S2S :
```
s2s_use_starttls: required
## Store the plain passwords or hashed for SCRAM:
auth_password_format: scram
```
On met aussi en place la connexion à la base de données pour ejabberd :
```
auth_method: sql
sql_type: pgsql
sql_server: "localhost"
sql_database: "ejabberd"
sql_username: "ejabberd"
sql_pool_size: 10
new_sql_schema: true
default_db: sql
```
On paramètre notre système de génération de captcha :
```
## Full path to a script that generates the image.
captcha_cmd: "/opt/chalec-xmpp-outils/captcha/captcha.sh"
captcha_url: https://xmpp.chalec.org:5444/captcha
registration_timeout: 60
```
On active l'inscription "in-band" :
```
mod_register:
## Only accept registration requests from the "trusted"
## network (see access_rules section above).
## Think twice before enabling registration from any
## address. See the Jabber SPAM Manifesto for details:
## https://github.com/ge0rg/jabber-spam-fighting-manifesto
ip_access: all
access: chalec_server
captcha_protected: true
registration_watchers: [admin@chalec.org]
welcome_message:
subject: Message de bienvenue
body: "Salut! Nous vous souhaitons la bienvenue sur l'instance XMPP de Chalec,
opérée par l'association Libre en Communs !
Pour plus d'informations sur nos actions : https://www.a-lec.org
Vous pouvez également rejoindre le salon public de l'association ici : xmpp:a-lec@salons.a-lec.org?join
Vous souhaitant un bon usage de nos services,
Librement,
L'équipe de Chalec."
```
On paramètre les quotas pour le téléversement de fichiers :
```
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
500: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
soft_upload_quota: #MiB
250: all
hard_upload_quota: #MiB
255: all
mod_http_upload:
hosts: ["xmpp.@HOST@"]
put_url: "https://xmpp.@HOST@:5444/upload"
get_url: "https://xmpp.@HOST@:5444/upload"
docroot: /var/www/upload
max_size: 500000000 # 500 MB
thumbnail: false
file_mode: "0644"
dir_mode: "2755"
secret_length: 20
jid_in_url: sha1
custom_headers:
"Access-Control-Allow-Origin": "https://@HOST@"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_http_upload_quota:
max_days: 30
```
On corrige la configuration de PEP :
```
mod_pubsub:
hosts:
- "pubsub.@HOST@"
- "news.@HOST@"
- "comments.@HOST@"
access_createnode: pubsub_createnode
ignore_pep_from_offline: false
last_item_cache: false
max_items_node: 1000
default_node_config:
max_items: 1000
plugins:
- flat
- pep
force_node_config:
"eu.siacs.conversations.axolotl.*":
access_model: open
## Avoid buggy clients to make their bookmarks public
storage:bookmarks:
access_model: whitelist
"urn:xmpp:bookmarks:0":
access_model: whitelist
send_last_published_item: never
persist_items: true
max_items: infinity
"urn:xmpp:bookmarks:1":
access_model: whitelist
send_last_published_item: never
persist_items: true
max_items: infinity
"urn:xmpp:pubsub:movim-public-subscription":
access_model: whitelist
persist_items: true
max_items: infinity
"storage:bookmarks":
access_model: whitelist
"urn:xmpp:microblog:0":
max_items: infinity
access_model: presence
notify_retract: true
persist_items: true
"urn:xmpp:microblog:0:comments*":
max_items: infinity
access_model: open
notify_retract: true
persist_items: true
```
On paramètre le gateway Matrix. Il faut générer une clé privée dans un shell `erl` :
```
=(^-^)=root@xmpp.chalec.org:~# erl
Erlang/OTP 25 [erts-13.1.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Eshell V13.1.5 (abort with ^G)
1> base64:encode(element(2, crypto:generate_key(eddsa, ed25519))).
<<"CLE PRIVEE">>
2> q().
ok
```
On paramètre le module dans la conf ejabberd :
```
mod_matrix_gw:
## Matrix federation related
matrix_domain: "matrix.chalec.org"
key_name: "key1"
# secret private key for matrix federation
key: "CLE PRIVEE"
```
Et enfin, pour que les appels audio/vidéo fonctionnent correctement :
```
mod_stun_disco: {}
```
Pour le client Movim actuel, ajouter :
```
# We are using movim here, which does not work with SASL downgrade protection
disable_sasl_scram_downgrade_protection: true
```
On veut également que ejabberd mette à jour le schema sql :
```
# We want that ejabberd takes care of its schema
update_sql_schema: true
```
Note : il faut penser également à paramétrer un compte administrateur dans la section `acl` et d'autres autorisations :
```
s2s_access: s2s
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
s2s:
- allow # to allow Matrix federation
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
chalec_server:
allow: chalec
```
Une fois la configuration effectuée on recharge ejabberd avec :
```
sudo ejabberdctl reload_config
```
Le débogage peut se faire à l'aide du fichier journal `/var/log/ejabberd/ejabberd.log`.
## Installation et configuration de Biboumi
On installe le paquet `biboumi` depuis les dépôts de Debian stable :
```
sudo apt install biboumi
```
On crée un utilisateur et un rôle pour psql :
```
sudo adduser _biboumi
sudo -u _biboumi psql
CREATE ROLE biboumi LOGIN PASSWORD '***masqué***';
```
On configure ensuite dans `/etc/biboumi/biboumi.cfg`.
Pour Biboumi il faut configurer la connexion à la base de données (créer un utilisateur dédié dans pgsql est le mieux à faire). On paramètre aussi la customisation des noms d'utilisateurs pour que les utilisateurs puissent changer de nick sur IRC. On rend les canaux IRC persistants pour que l'historique soit enregistré lorsque l'utilisateur est hors-ligne (effet BNC/ZNC) :
```
hostname=irc.chalec.org
password=***masqué***
xmpp_server_ip=127.0.0.1
port=8888
admin=admin@chalec.org
realname_customization=true
realname_from_jid=true
persistent_by_default=true
ca_file=
outgoing_bind=
log_level=1
db_name=postgresql://_biboumi:***masqué***@localhost
```
On oublie pas d'indiquer à ejabberd que Biboumi existe dans `/etc/ejabberd/ejabberd.yml`, en choississant son sous-domaine (ici, irc.chalec.org) :
```
listen:
[...]
-
port: 8888
ip: "127.0.0.1"
module: ejabberd_service
access: all
hosts:
"irc.chalec.org":
password: ***masqué***
```
On pense enfin à recharger la configuration d'ejabberd avec `sudo ejabberdctl reload_config` et à démarrer le service biboumi.service avec `systemctl`.
## Création d'un premier compte
```
sudo ejabberdctl register admin@chalec.org mot_de_passe
```
## Installation d'un serveur web pour rediriger vers la page du site www.chalec.org et déployer statoolinfos
On utilise le serveur `nginx` des dépôts Debian.
```
sudo apt install nginx
```
On crée le fichier de configuration approprié pour notre service (cf [documentation infrastructure](https://git.a-lec.org/a-lec/commissions/infrastructure/doc-infra/-/blob/master/Serveurs/routeur.md))
<details>
server
{
listen 80;
listen [::]:80;
server_name xmpp.chalec.org;
access_log /var/log/nginx/xmpp.chalec.org-access.log;
error_log /var/log/nginx/xmpp.chalec.org-error.log;
return 302 https://xmpp.chalec.org$request_uri;
}
server
{
listen 444 ssl proxy_protocol;
listen [::]:443 ssl;
set_real_ip_from 192.168.0.1;
real_ip_header proxy_protocol;
server_name xmpp.chalec.org;
root /var/www/html;
access_log /var/log/nginx/xmpp.chalec.org-access.log;
error_log /var/log/nginx/xmpp.chalec.org-error.log;
ssl_certificate /etc/letsencrypt/live/xmpp.chalec.org/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/xmpp.chalec.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
# Add index.php to the list if you are using PHP
index index.html index.htm index.php index.xhtml;
# StatoolInfos.
include /etc/nginx/statoolinfos.conf;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
return 302 https://www.chalec.org/services/xmpp.html;
}
ssi on;
ssi_last_modified on;
# pass PHP scripts to FastCGI server
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
</details>
## Installation du client web movim
### Prérequis
Installer les paquets :
```
sudo apt install composer php-fpm php-curl php-mbstring php-imagick php-gd php-pgsql php-xml
```
### Installation du serveur movim
#### Récupération de la dernière version
Se placer dans le répertoire web :
```
cd /var/www
```
Cloner le dépôt de code de movim :
```
sudo -u www-data git clone https://github.com/movim/movim.git && cd movim
```
Récupérer la dernière version stable (ici : `v0.21`)
```
sudo -u www-data git checkout v0.21
```
On crée la branche dédiée :
```
sudo -u www-data git branch xmpp.chalec.org-v0.21
sudo -u www-data git checkout xmpp.chalec.org-v0.21
```
#### Déploiement avec php-composer
```
cd var/www/movim
sudo -u www-data composer install
```
#### Création de la base de données
```
sudo -i -u postgres
createuser --interactive # créer le rôle movim avec les permissions minimales
sudo -u postgres psql
CREATE DATABASE movim OWNER movim;
```
#### Configuration de movim
En root :
```
chown www-data movim && chown www-data movim/public && chmod u+rwx movim
```
On crée le fichier de configuration :
```
cp /var/www/movim/.env.example /var/www/movim/.env
```
On crée le service systemd :
```
cp etc/systemd/system/movim.service /etc/systemd/system/
```
On édite ensuite le fichier `/var/www/movim/.env` :
```
# Database configuration
DB_DRIVER=pgsql
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=movim
DB_USERNAME=movim
DB_PASSWORD=movim
# Daemon configuration
DAEMON_URL=https://xmpp.chalec.org/ # Public URL of your Movim instance
DAEMON_PORT=8080 # Port on which the daemon will listen
DAEMON_INTERFACE=127.0.0.1 # Interface on which the daemon will listen, must be an IP
DAEMON_DEBUG=false
DAEMON_VERBOSE=false
```
Peupler la base de données avec cette configuration :
```
sudo -u www-data composer movim:migrate
```
Activer `opcache` dans `/etc/php/7.4/fpm/php.ini` :
```
[opcache]
; Determines if Zend OPCache is enabled
opcache.enable=1
; Determines if Zend OPCache is enabled for the CLI version of PHP
opcache.enable_cli=1
```
Créer l'utilisateur d'administration (<jid> étant son identifiant) :
```
php daemon.php setAdmin <jid>
```
#### Configuration du serveur web nginx
On ajoute/modifie dans le fichier `/etc/nginx/sites-enabled/xmpp.chalec.org.conf` :
```
fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=nginx_cache:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
root /var/www/movim/public;
location /picture {
include fastcgi_params;
add_header X-Cache $upstream_cache_status;
fastcgi_ignore_headers "Cache-Control" "Expires" "Set-Cookie";
fastcgi_cache nginx_cache;
fastcgi_cache_key $request_method$host$request_uri;
fastcgi_cache_valid any 7d;
}
location /ws/ {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
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 https;
proxy_redirect off;
}
}
```
### Mise à jour du serveur movim
Avec `vxxx` la dernière version :
```
cd /var/www/movim
sudo -u www-data git fetch
sudo -u www-data git branch xmpp.chalec.org-vxxx
sudo -u www-data git checkout xmpp.chalec.org-vxxx
sudo -u www-data git merge vxxx
sudo -u www-data composer install
```
# Participation à XMPP Providers
La participation à [XMPP Providers](https://providers.xmpp.net) implique la création du fichier `/var/www/html/xmpp-provider-v2.json` :
```
{
"website": {
"fr": "https://www.chalec.org/services/xmpp/"
},
"alternativeJids": [],
"busFactor": 3,
"organization": "non-governmental",
"passwordReset": {},
"serverTesting": true,
"maximumHttpFileUploadTotalSize": 500,
"maximumHttpFileUploadStorageTime": 30,
"maximumMessageArchiveManagementStorageTime": 30,
"professionalHosting": true,
"freeOfCharge": true,
"legalNotice": {
"fr": "https://www.chalec.org/mentions-legales.html"
},
"serverLocations": [
"fr"
],
"since": "2022-08-10"
}
}
```
Il faut mettre ce fichier à jour lors d'un changement de politique.