#!/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 < 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:]]*]*: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 "────────────────────────────────────────────────────────────"