- stats.html : bouton "Générer et ouvrir" avec polling async ; supprime le window.open automatique (bloqué par les navigateurs) - app.py : routes POST /stats/generate et GET /stats/status ; exécution GoAccess en thread daemon, verrou anti-doublon - .env.example : documente STATS_LOG_FILE et STATS_GENERATE_CMD - README.md : flux de publication local→git→serveur, variables d'env, procédure première installation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
131 lines
5.2 KiB
Bash
Executable file
131 lines
5.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# deploy-app.sh — déploie l'app Flask (static/app/) sur static.alpinux.org
|
|
#
|
|
# Usage :
|
|
# ./deploy-app.sh # déploie et redémarre le service
|
|
# ./deploy-app.sh -n # dry-run (aucune modification)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
APP_DIR="$SCRIPT_DIR/../app"
|
|
ENV_FILE="$SCRIPT_DIR/../.env"
|
|
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'
|
|
BOLD='\033[1m'; RESET='\033[0m'
|
|
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
echo -e "${RED}Erreur : .env introuvable. Copier .env.example et remplir.${RESET}"
|
|
exit 1
|
|
fi
|
|
# shellcheck source=/dev/null
|
|
source "$ENV_FILE"
|
|
|
|
REMOTE_HOST="${STATIC_HOST:?Variable STATIC_HOST manquante dans .env}"
|
|
REMOTE_DEST="/opt/static-cdn"
|
|
SERVICE_FILE="$SCRIPT_DIR/../../infra/services/static-cdn.service"
|
|
|
|
DRY_RUN=false
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-n|--dry-run) DRY_RUN=true ;;
|
|
-h|--help) sed -n '2,5p' "$0" | sed 's/^# //'; exit 0 ;;
|
|
esac
|
|
done
|
|
|
|
echo -e "${BOLD}Déploiement de l'app Flask → $REMOTE_HOST:$REMOTE_DEST${RESET}"
|
|
echo ""
|
|
|
|
# ── 1. Rsync de l'app ────────────────────────────────────────────────
|
|
echo -e "${CYAN}[1/4] Synchronisation des fichiers…${RESET}"
|
|
RSYNC_OPTS=(-rlcz --delete --human-readable
|
|
--exclude='.env' --exclude='__pycache__/' --exclude='*.pyc'
|
|
--exclude='venv/' --exclude='.env.example')
|
|
|
|
if $DRY_RUN; then
|
|
rsync --dry-run --itemize-changes "${RSYNC_OPTS[@]}" "$APP_DIR/" "$REMOTE_HOST:$REMOTE_DEST/"
|
|
echo -e "${CYAN}Mode dry-run — aucune modification effectuée.${RESET}"
|
|
exit 0
|
|
fi
|
|
|
|
ssh "$REMOTE_HOST" "sudo mkdir -p $REMOTE_DEST && sudo chown abonnelc:abonnelc $REMOTE_DEST"
|
|
rsync "${RSYNC_OPTS[@]}" "$APP_DIR/" "$REMOTE_HOST:$REMOTE_DEST/"
|
|
echo -e " ${GREEN}✓ Fichiers copiés${RESET}"
|
|
|
|
# ── 2. Environnement Python ──────────────────────────────────────────
|
|
echo -e "${CYAN}[2/4] Mise à jour de l'environnement Python…${RESET}"
|
|
ssh "$REMOTE_HOST" bash <<'ENDSSH'
|
|
set -e
|
|
cd /opt/static-cdn
|
|
[ ! -d venv ] && python3 -m venv venv
|
|
venv/bin/pip install --quiet --upgrade pip
|
|
venv/bin/pip install --quiet -r requirements.txt
|
|
ENDSSH
|
|
echo -e " ${GREEN}✓ Dépendances installées${RESET}"
|
|
|
|
# ── 3. Fichier .env distant ──────────────────────────────────────────
|
|
echo -e "${CYAN}[3/4] Vérification du fichier .env distant…${RESET}"
|
|
ENV_EXISTS=$(ssh "$REMOTE_HOST" "test -f $REMOTE_DEST/.env && echo yes || echo no")
|
|
if [ "$ENV_EXISTS" = "no" ]; then
|
|
echo -e " ${RED}ATTENTION : /opt/static-cdn/.env absent sur le serveur.${RESET}"
|
|
echo " Créer le fichier avec les variables requises :"
|
|
echo " ssh $REMOTE_HOST"
|
|
echo " nano /opt/static-cdn/.env"
|
|
echo " Variables minimales :"
|
|
echo " SECRET_KEY=<valeur-aleatoire>"
|
|
echo " ALPID_CLIENT_ID=<client-keycloak>"
|
|
echo " ALPID_CLIENT_SECRET=<secret>"
|
|
echo " ALPID_DISCOVERY_URL=https://alpid.alpinux.org/realms/master/.well-known/openid-configuration"
|
|
echo " ADMIN_EMAILS=cedric.alpinux@acemail.fr"
|
|
echo " ASSETS_ROOT=/var/www/clients/client1/web17/web"
|
|
echo " STATS_FILE=/opt/static-cdn/goaccess.html"
|
|
echo " STATS_JSON=/opt/static-cdn/goaccess.json"
|
|
echo " STATS_LOG_FILE=/var/log/ispconfig/httpd/static.alpinux.org/access.log"
|
|
echo " STATS_GENERATE_CMD=goaccess \$STATS_LOG_FILE --config-file=/var/log/ispconfig/httpd/static.alpinux.org/goaccess.conf -o \$STATS_FILE -o \$STATS_JSON"
|
|
echo ""
|
|
else
|
|
echo -e " ${GREEN}✓ .env présent${RESET}"
|
|
fi
|
|
|
|
# ── 4. Service systemd ───────────────────────────────────────────────
|
|
echo -e "${CYAN}[4/4] Déploiement du service systemd…${RESET}"
|
|
scp "$SERVICE_FILE" "$REMOTE_HOST:/tmp/static-cdn.service"
|
|
ssh "$REMOTE_HOST" bash <<'ENDSSH'
|
|
set -e
|
|
sudo mkdir -p /var/log/static-cdn
|
|
sudo chown abonnelc:abonnelc /var/log/static-cdn
|
|
sudo cp /tmp/static-cdn.service /etc/systemd/system/static-cdn.service
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable static-cdn
|
|
if systemctl is-active --quiet static-cdn; then
|
|
sudo systemctl restart static-cdn
|
|
echo "Service redémarré."
|
|
else
|
|
sudo systemctl start static-cdn 2>/dev/null || true
|
|
echo "Service démarré."
|
|
fi
|
|
ENDSSH
|
|
echo -e " ${GREEN}✓ Service systemd actif${RESET}"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}✓ Déploiement terminé.${RESET}"
|
|
echo ""
|
|
echo -e "${BOLD}Étape manuelle restante — ISPConfig :${RESET}"
|
|
echo " https://owni.alpinux.org:8080 → Sites → static.alpinux.org → Directives Apache"
|
|
echo ""
|
|
echo " Coller dans le champ 'Directives Apache SSL' :"
|
|
echo ""
|
|
cat << 'EOF'
|
|
# CDN public → Apache sert directement depuis DocumentRoot
|
|
ProxyPass /logo/ !
|
|
ProxyPass /wiki/ !
|
|
ProxyPass /error/ !
|
|
ProxyPass /favicon.ico !
|
|
ProxyPass /robots.txt !
|
|
|
|
# Tableau de bord → Flask (inclut /stats/ avec auth SSO)
|
|
RequestHeader set X-Forwarded-Proto "https"
|
|
ProxyPreserveHost On
|
|
ProxyPass / http://127.0.0.1:5003/
|
|
ProxyPassReverse / http://127.0.0.1:5003/
|
|
EOF
|