alpinux.presentations/deploy/installer.sh
Cédrix 02cf82447b Créer le site des présentations d'Alpinux
Un dossier par présentation en Markdown, converti en diaporama HTML autonome
par Marp CLI, et une page d'accueil générée qui les liste toutes.

- scripts/build.mjs : build strict (fiche validée, images vérifiées, aucune
  ressource externe hormis le logo), page d'accueil filtrable,
  presentations.json et .htaccess pour l'en-tête CORS
- theme/alpinux.css : thème commun pour la vidéoprojection, classes titre et demo
- slides/_modele : modèle commenté, non publié
- slides/pdf-signer : « Lire, remplir et signer ses PDF », avec notes d'orateur
- scripts/deploy-presentations.sh et deploy/ : déploiement par webhook Gitea,
  sur le modèle du wiki et de www

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M713yNBL8cssBA1Zri5QLT
2026-10-10 21:44:32 +02:00

161 lines
6.7 KiB
Bash
Executable file

#!/bin/bash
# Installe la chaîne de déploiement de presentations.alpinux.org sur owni. À lancer en
# root — relancer ne casse rien, chaque étape vérifie d'abord ce qui existe.
#
# sudo bash deploy/installer.sh
#
# Ce que ça met en place : Node.js dans /opt/presentations-alpinux/node, une clé de
# déploiement en lecture seule, un clone du dépôt, le service d'écoute du webhook sur
# 127.0.0.1:9878, le relais Apache /deploy, et le droit d'écriture de l'utilisateur du
# service sur le DocumentRoot.
#
# Le script s'arrête à l'étape 3 tant que la clé de déploiement n'est pas déclarée
# dans Gitea : la déclarer, puis relancer.
set -euo pipefail
BASE="/opt/presentations-alpinux"
REPO_DIR="$BASE/repo"
UTILISATEUR="abonnelc"
CIBLE="/var/www/clients/client1/web22/web"
VHOST="/etc/apache2/sites-available/presentations.alpinux.org.vhost"
SECRET_FICHIER="/etc/default/presentations-webhook"
JOURNAL="/var/log/presentations-deploy.log"
UNITE="/etc/systemd/system/presentations-webhook.service"
PORT="9878"
# Node.js : la version LTS, figée. Pour en changer, modifier ce numéro et relancer.
NODE_VERSION="v24.21.0"
NODE_ARCHIVE="node-$NODE_VERSION-linux-x64.tar.xz"
NODE_URL="https://nodejs.org/dist/$NODE_VERSION"
# Le dépôt est tiré par SSH, avec une clé qui ne sert qu'à lui.
CLE="/home/$UTILISATEUR/.ssh/id_ed25519_presentations_deploy"
ALIAS_SSH="gitea-presentations"
DEPOT_URL="$ALIAS_SSH:alpinux.cedrica5l/alpinux-presentations.git"
SOURCE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
[ "$(id -u)" -eq 0 ] || { echo "À lancer en root : sudo bash $0" >&2; exit 1; }
echo "==> 1/7 Node.js $NODE_VERSION dans $BASE/node"
install -d -o "$UTILISATEUR" -g "$UTILISATEUR" "$BASE"
if [ -x "$BASE/node/bin/node" ] && [ "$("$BASE/node/bin/node" --version)" = "$NODE_VERSION" ]; then
echo " (déjà là)"
else
tmp="$(mktemp -d)"
curl -fsSL -o "$tmp/$NODE_ARCHIVE" "$NODE_URL/$NODE_ARCHIVE"
curl -fsSL -o "$tmp/SHASUMS256.txt" "$NODE_URL/SHASUMS256.txt"
(cd "$tmp" && grep " $NODE_ARCHIVE\$" SHASUMS256.txt | sha256sum -c -)
rm -rf "$BASE/node"
install -d "$BASE/node"
tar -xJf "$tmp/$NODE_ARCHIVE" -C "$BASE/node" --strip-components=1 --no-same-owner
rm -rf "$tmp"
echo " $("$BASE/node/bin/node" --version) installé"
fi
echo "==> 2/7 Clé de déploiement"
if [ ! -f "$CLE" ]; then
sudo -u "$UTILISATEUR" ssh-keygen -q -t ed25519 -N "" -C "deploy@presentations.alpinux.org" -f "$CLE"
echo " clé créée"
fi
CONFIG_SSH="/home/$UTILISATEUR/.ssh/config"
if ! grep -q "^Host $ALIAS_SSH\$" "$CONFIG_SSH" 2>/dev/null; then
sudo -u "$UTILISATEUR" tee -a "$CONFIG_SSH" > /dev/null <<EOF
Host $ALIAS_SSH
HostName alpinux.org
Port 3022
User git
IdentityFile $CLE
IdentitiesOnly yes
EOF
chmod 600 "$CONFIG_SSH"
echo " alias SSH « $ALIAS_SSH » ajouté"
fi
echo "==> 3/7 Dépôt dans $REPO_DIR"
if [ -d "$REPO_DIR/.git" ]; then
sudo -u "$UTILISATEUR" git -C "$REPO_DIR" pull --ff-only origin main
elif ! sudo -u "$UTILISATEUR" git clone "$DEPOT_URL" "$REPO_DIR"; then
echo
echo "Le serveur n'a pas pu cloner le dépôt. Déclarer cette clé publique dans Gitea :" >&2
echo " dépôt alpinux-presentations → Paramètres → Clés de déploiement → Ajouter" >&2
echo " (sans cocher l'accès en écriture)" >&2
echo
cat "$CLE.pub"
echo
echo "Puis relancer : sudo bash $0" >&2
exit 1
fi
echo "==> 4/7 Scripts et journal"
# Le serveur exécute ces copies, pas les fichiers du dépôt : une modification de
# deploy/ ou de scripts/deploy-presentations.sh ne prend effet qu'en relançant
# installer.sh. Un push ne peut donc pas changer ce que le service exécute.
install -o "$UTILISATEUR" -g "$UTILISATEUR" -m 755 "$SOURCE/scripts/deploy-presentations.sh" "$BASE/deploy-presentations.sh"
install -o "$UTILISATEUR" -g "$UTILISATEUR" -m 755 "$SOURCE/deploy/webhook.py" "$BASE/webhook.py"
touch "$JOURNAL" && chown "$UTILISATEUR":"$UTILISATEUR" "$JOURNAL"
echo "==> 5/7 Droit d'écriture sur $CIBLE"
# Le DocumentRoot appartient à web22 ; une ACL suffit à y laisser écrire le service,
# sans toucher au propriétaire ni aux droits qu'attend ISPConfig.
setfacl -m "u:$UTILISATEUR:rwx" "$CIBLE"
echo "==> 6/7 Secret du webhook et service systemd"
if [ -f "$SECRET_FICHIER" ]; then
echo " (secret déjà là, inchangé)"
else
(umask 077; printf 'PRESENTATIONS_WEBHOOK_SECRET=%s\n' "$(openssl rand -hex 24)" > "$SECRET_FICHIER")
fi
chmod 600 "$SECRET_FICHIER"
install -m 644 "$SOURCE/deploy/presentations-webhook.service" "$UNITE"
systemctl daemon-reload
systemctl enable --now presentations-webhook
systemctl restart presentations-webhook
systemctl is-active --quiet presentations-webhook && echo " service actif"
echo "==> 7/7 Relais Apache /deploy"
if grep -q "127.0.0.1:$PORT" "$VHOST"; then
echo " déjà relayé"
else
cp -a "$VHOST" "$VHOST.bak-$(date +%Y%m%d%H%M)"
awk -v port="$PORT" '
{ print }
!fait && /^[[:space:]]*<VirtualHost[^>]*:443>/ {
print "\t\tProxyPass /deploy http://127.0.0.1:" port "/deploy"
print "\t\tProxyPassReverse /deploy http://127.0.0.1:" port "/deploy"
fait = 1
}
' "$VHOST" > "$VHOST.tmp"
# Recopié dans le fichier plutôt que déplacé par-dessus : un « mv » remplacerait
# l'original par un fichier neuf, avec d'autres droits.
cat "$VHOST.tmp" > "$VHOST" && rm -f "$VHOST.tmp"
grep -q "127.0.0.1:$PORT" "$VHOST" || { echo " ÉCHEC : relais non posé dans $VHOST" >&2; exit 1; }
echo " relais ajouté"
fi
if apache2ctl configtest; then
systemctl reload apache2
else
echo "Configuration Apache invalide : rien n'a été rechargé." >&2
echo "La sauvegarde .bak-* est à côté du vhost." >&2
exit 1
fi
echo
echo "────────────────────────────────────────────────────────────"
echo "Reste à faire à la main :"
echo
echo "1. Déclarer le webhook dans Gitea"
echo " dépôt alpinux-presentations → Paramètres → Webhooks → Ajouter → Gitea"
echo " URL : https://presentations.alpinux.org/deploy"
echo " Méthode : POST, type de contenu : application/json"
echo " Secret : sudo cat $SECRET_FICHIER"
echo " Événement : Push seulement, filtre de branche : main"
echo
echo "2. Recopier le relais dans ISPConfig pour qu'il survive à une régénération"
echo " du vhost : Sites → presentations.alpinux.org → Options → Directives Apache"
echo " (les deux lignes de deploy/apache-vhost.exemple.conf)"
echo
echo "Première mise en ligne, sans attendre un push :"
echo " sudo -u $UTILISATEUR $BASE/deploy-presentations.sh; tail -5 $JOURNAL"
echo "────────────────────────────────────────────────────────────"