Déploiement : commande forcée pour la clé de GitHub, qui ne peut plus que déployer un commit de main

This commit is contained in:
IliesAllali committed 2026-10-26 12:24:54 +01:00
1 parent 124ceb1c3e
commit 3bfacc5b1a
2 files changed
+55

No files matched your search

+17
View File
@@ -20,6 +20,7 @@ Chaque push sur `main` lance d'abord la CI (`.github/workflows/ci.yml`). Si elle
- `/etc/parenthese/build.env` : variables de build du front et de la landing (`VITE_POSTHOG_KEY`, `VITE_POSTHOG_HOST`)
- `/etc/cron.d/parenthese-backup` : sauvegarde nocturne par `deploy/backup.sh`
- `/etc/genealogy/backup.env` (facultatif) : rétention et envoi S3 des sauvegardes
- `/usr/local/sbin/parenthese-ssh-deploy` : copie de `deploy/ssh-deploy.sh`, commande forcée de la clé de déploiement (voir plus bas)
## Prérequis du serveur
@@ -28,3 +29,19 @@ Node 20, `pm2` en global, PostgreSQL joignable par `DATABASE_URL`, nginx configu
## Déployer à la main
`bash deploy/deploy.sh --sync` depuis le dépôt sur le serveur. `FORCE_FULL=1` pour tout reconstruire. Ne pas le lancer pendant un déploiement GitHub : le verrou le fera attendre.
## Clé de déploiement restreinte
La clé de GitHub ne doit pouvoir que déployer un commit de `main`, jamais lancer une autre commande sur le serveur. On la lie à `deploy/ssh-deploy.sh`, copié hors du dépôt parce que le déploiement réécrit le dépôt :
```
install -m 755 -o root -g root /var/www/parenthese/deploy/ssh-deploy.sh /usr/local/sbin/parenthese-ssh-deploy
```
Puis, dans `authorized_keys`, devant la ligne de la clé `github-actions-parenthese-public` :
```
command="/usr/local/sbin/parenthese-ssh-deploy",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA… github-actions-parenthese-public
```
Le workflow n'a pas à changer. Après une mise à jour de `deploy/ssh-deploy.sh`, refaire l'`install`.
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Commande forcée de la clé de déploiement GitHub, posée devant elle dans /root/.ssh/authorized_keys :
# command="/usr/local/sbin/parenthese-ssh-deploy",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA… github-actions-parenthese-public
# Avec elle, la clé ne peut plus que déployer un commit qui appartient déjà à main : une clé volée ne lance aucune
# autre commande. Le workflow « Deploy Hostinger » n'a pas à changer : il envoie
# FORCE_FULL=<0|1> DEPLOY_SHA=<sha> bash -s
# suivi d'un script sur l'entrée standard. Seuls FORCE_FULL et DEPLOY_SHA sont lus, le script envoyé est ignoré,
# et la suite reprend la même logique (verrou, commit de main, pas de retour en arrière, deploy.sh).
# Installé hors du dépôt, parce que le déploiement réécrit le dépôt pendant qu'il tourne :
# install -m 755 -o root -g root /var/www/parenthese/deploy/ssh-deploy.sh /usr/local/sbin/parenthese-ssh-deploy
set -euo pipefail
if ! [[ "${SSH_ORIGINAL_COMMAND:-}" =~ ^FORCE_FULL=([01])\ DEPLOY_SHA=([0-9a-f]{40})\ bash\ -s$ ]]; then
echo "Commande refusée : cette clé ne sert qu'à déployer" >&2
exit 1
fi
FORCE_FULL="${BASH_REMATCH[1]}"
DEPLOY_SHA="${BASH_REMATCH[2]}"
# Le script envoyé par le workflow n'est pas exécuté
cat > /dev/null
cd /var/www/parenthese
exec flock -w 900 /tmp/parenthese-deploy.lock env PARENTHESE_DEPLOY_LOCKED=1 FORCE_FULL="$FORCE_FULL" DEPLOY_SHA="$DEPLOY_SHA" bash -c '
set -euo pipefail
git fetch -q origin main
# Le commit validé doit appartenir à main
if ! git merge-base --is-ancestor "$DEPLOY_SHA" origin/main; then
echo "Commit $DEPLOY_SHA absent de main : rien n est déployé" >&2
exit 1
fi
# Un déploiement plus récent est déjà en ligne : pas de retour en arrière
if [ "$(git rev-parse HEAD)" != "$DEPLOY_SHA" ] && git merge-base --is-ancestor "$DEPLOY_SHA" HEAD; then
echo "Version plus récente déjà déployée, $DEPLOY_SHA ignoré"
exit 0
fi
git reset -q --hard "$DEPLOY_SHA"
bash deploy/deploy.sh
'