Le dépôt a été créé sur la forge sous le nom alpinux.presentations, et non alpinux-presentations : adresses de clonage, lien de la page d'accueil et consignes d'installation sont alignés. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M713yNBL8cssBA1Zri5QLT
9.2 KiB
Déploiement automatique : mise en place côté serveur
Cette page s'adresse aux mainteneurs qui ont un accès SSH à alpinux.org. Les
contributeurs n'ont rien à faire ici : leur travail s'arrête à la pull request.
La chaîne est la même que celle du wiki et de www.alpinux.org :
push sur main → webhook Gitea → https://presentations.alpinux.org/deploy
│ Apache relaie vers 127.0.0.1:9878
▼
service d'écoute (signature HMAC vérifiée)
▼
deploy-presentations.sh : git pull → npm ci → build dans le staging → rsync
▼
https://presentations.alpinux.org
Si le build échoue — front matter invalide, image manquante — rien n'est copié : le site en ligne reste celui du dernier build réussi.
Un second service plutôt qu'une nouvelle route
Le service d'écoute du wiki (/opt/wiki-mkdocs/webhook.py) ne connaît qu'un secret et
qu'un script. Y ajouter une route aurait demandé de le réécrire, de faire cohabiter
deux secrets dans la même unité systemd, et de redémarrer le déploiement du wiki à
chaque retouche de celui des présentations.
Ce dépôt apporte donc son propre service, comme www.alpinux.org l'a fait avant lui. Les trois sont des copies du même petit programme :
| Site | Service systemd | Port | Secret |
|---|---|---|---|
| wiki | wiki-webhook |
9876 | dans l'unité systemd |
| www | www-webhook |
9877 | /etc/default/www-webhook |
| présentations | presentations-webhook |
9878 | /etc/default/presentations-webhook |
Chaque dépôt a son secret : celui des présentations n'ouvre pas le déploiement du wiki, et inversement.
Ce qui est installé, et où
| Quoi | Où |
|---|---|
| Clone du dépôt | /opt/presentations-alpinux/repo |
| Répertoire de staging | /opt/presentations-alpinux/staging |
| Node.js (LTS, version figée) | /opt/presentations-alpinux/node |
| Script de déploiement (copie) | /opt/presentations-alpinux/deploy-presentations.sh |
| Service d'écoute (copie) | /opt/presentations-alpinux/webhook.py |
| Unité systemd | /etc/systemd/system/presentations-webhook.service |
Secret HMAC (0600, root) |
/etc/default/presentations-webhook |
| Clé de déploiement, lecture seule | ~abonnelc/.ssh/id_ed25519_presentations_deploy |
| DocumentRoot | /var/www/clients/client1/web22/web |
| Journal | /var/log/presentations-deploy.log |
Fichiers fournis par ce dossier : installer.sh,
webhook.py, presentations-webhook.service,
apache-vhost.exemple.conf, et
../scripts/deploy-presentations.sh.
Aucun secret n'est dans le dépôt. Le secret du webhook est tiré au hasard sur le
serveur par installer.sh ; la clé privée de déploiement y est créée et n'en sort pas.
Installation
Tout tient dans installer.sh, à lancer en root. Il est sans danger de le relancer :
chaque étape vérifie d'abord ce qui existe.
sudo bash deploy/installer.sh
- Node.js — téléchargé depuis nodejs.org, somme SHA-256 vérifiée, déposé dans
/opt/presentations-alpinux/node. Rien n'est ajouté aux dépôts apt du serveur, et pas de Chromium : le build HTML de Marp n'en a pas besoin. - Clé de déploiement — une clé SSH propre à ce dépôt, et un alias
gitea-presentationsdans~abonnelc/.ssh/config. - Clone du dépôt. La première fois, le script s'arrête ici et affiche la clé publique : la déclarer dans Gitea, Paramètres → Clés de déploiement du dépôt, sans l'accès en écriture, puis relancer.
- Scripts — copie de
deploy-presentations.shet dewebhook.pydans/opt/presentations-alpinux, création du journal. - Droit d'écriture sur le DocumentRoot, par une ACL pour
abonnelc. - Secret et service — secret tiré au hasard s'il n'existe pas, unité systemd installée et démarrée.
- Relais Apache — les deux lignes
ProxyPassdans le vhost, puis rechargement d'Apache si la configuration est valide.
Déclarer le webhook dans Gitea
Dans le dépôt alpinux.presentations : Paramètres → Webhooks → Ajouter un webhook →
Gitea.
| Champ | Valeur |
|---|---|
| URL cible | https://presentations.alpinux.org/deploy |
| Méthode HTTP | POST |
| Type de contenu | application/json |
| Secret | la valeur lue par sudo cat /etc/default/presentations-webhook |
| Déclencheur | Push seulement |
| Filtre de branche | main |
Le filtre de branche évite des appels inutiles ; le service ignore de toute façon tout
ce qui ne vise pas refs/heads/main.
Rendre le relais Apache durable
Le vhost est écrit par ISPConfig, qui le régénère à chaque modification du site
(certificat, alias, version de PHP…). Les deux lignes posées par installer.sh
disparaissent ce jour-là.
Pour qu'elles tiennent : dans ISPConfig, Sites → presentations.alpinux.org → Options →
Directives Apache, coller les deux lignes de
apache-vhost.exemple.conf. ISPConfig les réécrira alors
avec le reste du vhost.
Vérifier
# Le service tourne et n'écoute que sur la boucle locale
systemctl status presentations-webhook
ss -ltn | grep 9878
# Sans signature valable, le relais répond 403 — c'est la bonne réponse
curl -s -o /dev/null -w '%{http_code}\n' -X POST -d '{}' https://presentations.alpinux.org/deploy
# Le dernier déploiement
tail -20 /var/log/presentations-deploy.log
Une exécution réussie encadre le build par une ligne Deploy started et une ligne
Deploy done. Une ligne ABANDON signale un échec : la cause est juste au-dessus, et
le site en ligne n'a pas bougé.
Dans Gitea, la page du webhook liste les envois récents avec la réponse reçue, et son bouton Tester l'envoi rejoue un push.
Au quotidien
| Je veux… | Je fais… |
|---|---|
| Savoir pourquoi ce n'est pas en ligne | tail -30 /var/log/presentations-deploy.log |
| Republier sans nouveau commit | sudo -u abonnelc /opt/presentations-alpinux/deploy-presentations.sh |
Appliquer une modification de deploy/ |
sudo bash /opt/presentations-alpinux/repo/deploy/installer.sh |
| Changer de version de Node.js | modifier NODE_VERSION dans installer.sh, pousser, relancer installer.sh |
| Changer le secret | supprimer /etc/default/presentations-webhook, relancer installer.sh, mettre à jour le webhook dans Gitea |
Les pièges à connaître
Le serveur exécute des copies. deploy-presentations.sh et webhook.py sont
copiés dans /opt/presentations-alpinux par installer.sh. Les modifier dans le dépôt
ne change rien tant que installer.sh n'a pas été relancé. C'est voulu : une pull
request fusionnée ne peut pas, à elle seule, changer ce que le service exécute.
Mais le build, lui, exécute le dépôt. scripts/build.mjs et les dépendances de
package-lock.json tournent sur le serveur à chaque push, sous le compte du service.
Une pull request qui touche à scripts/, à package.json ou à package-lock.json se
relit donc comme du code qui s'exécutera sur le serveur — pas comme une diapo.
rsync --delete épargne deux dossiers. error/ et stats/ appartiennent à
ISPConfig et sont exclus de la synchronisation. Tout autre fichier déposé à la main
dans le DocumentRoot est supprimé au déploiement suivant.
Le droit d'écriture tient à une ACL. Si ISPConfig réinitialise les droits du site,
le déploiement échoue sur une erreur de permission : relancer installer.sh la repose.
Node.js ne se met pas à jour tout seul. Il est installé hors d'apt. Suivre les
versions LTS sur https://nodejs.org/fr/about/previous-releases et changer
NODE_VERSION de temps en temps.