alpinux-static/README.md
Alpinux 16c1af4143 feat: génération GoAccess à la demande + README complet
- 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>
2026-05-03 20:39:25 +02:00

7.9 KiB

static.alpinux.org

CDN pour les fichiers binaires et assets statiques de l'association : logos, favicons, images Open Graph. Tableau de bord d'administration accessible sur https://static.alpinux.org (authentification AlpID).


Flux de publication

Il y a deux cibles distinctes sur le serveur, gérées par des scripts séparés :

Quoi Destination serveur Script Passe par git ?
Assets CDN (logo/, wiki/, stats/, error/…) /var/www/clients/client1/web17/web push-assets.sh Non — rsync direct
App Flask (app/) /opt/static-cdn/ + redémarrage service deploy-app.sh Non — rsync direct

Git sert à versionner et sauvegarder le code sur Gitea. Il n'est pas dans la boucle de déploiement : les scripts rsynchent depuis le dépôt local, pas depuis Gitea.

Modifier les assets CDN (logo, wiki, stats…)

# 1. Modifier les fichiers dans static/
# 2. Versionner (optionnel mais recommandé)
git add <fichiers>
git commit -m "..."
git push                        # sauvegarde sur gitea.alpinux.org

# 3. Pousser sur le serveur
./scripts/push-assets.sh        # aperçu + confirmation
./scripts/push-assets.sh -y     # sans confirmation

push-assets.sh exclut automatiquement app/, scripts/, .git/, .env, README.md. Il envoie : logo/, wiki/, stats/, error/, favicon.ico, robots.txt, standard_index.html.

Modifier l'app Flask (app/)

# 1. Modifier les fichiers dans static/app/
# 2. Versionner
git add app/
git commit -m "..."
git push                        # sauvegarde sur gitea.alpinux.org

# 3. Déployer sur le serveur
./scripts/deploy-app.sh         # rsync + pip install + restart service
./scripts/deploy-app.sh -n      # dry-run

deploy-app.sh rsync app/ vers /opt/static-cdn/, met à jour le venv Python, et redémarre le service systemd static-cdn.


Contenu hébergé

Fichier Usage
logo/alpinux-logo-512.png Logo 512 px — page d'accueil alpinux.org, balises OG
logo/alpinux-logo-192.png Logo 192 px — PWA / Android home screen
logo/favicon-32.png Favicon 32 px
logo/favicon-16.png Favicon 16 px
logo/favicon.ico Favicon ICO multi-taille
wiki/ Images pour wiki.alpinux.org

Configuration locale (.env)

cp .env.example .env
Variable Obligatoire Description
STATIC_HOST oui Alias SSH ou nom d'hôte (alpinux.org)
STATIC_PATH oui Chemin absolu du web root sur le serveur
LOCAL_ASSETS_DIR oui Chemin absolu du dépôt local (static/)
STATIC_USER non Login SSH — laisser vide si ~/.ssh/config définit l'utilisateur

Si l'hôte est déclaré dans ~/.ssh/config (recommandé), laisser STATIC_USER vide. Sinon, renseigner STATIC_USER=<login> — les scripts construisent alors USER@HOST:PATH.


Scripts

# Synchroniser les assets CDN
./scripts/pull-assets.sh        # serveur → local (aperçu + confirmation)
./scripts/pull-assets.sh -y     # sans confirmation
./scripts/pull-assets.sh -n     # dry-run

./scripts/push-assets.sh        # local → serveur (aperçu + confirmation)
./scripts/push-assets.sh -y     # sans confirmation
./scripts/push-assets.sh -n     # dry-run

# Déployer l'app Flask
./scripts/deploy-app.sh         # déploie et redémarre le service
./scripts/deploy-app.sh -n      # dry-run

Tableau de bord Flask (app/)

Application Flask déployée sur le serveur via deploy-app.sh. Accessible sur https://static.alpinux.org (proxy Apache → 127.0.0.1:5003). Authentification SSO via AlpID (Keycloak).

Fonctionnalités

Route Description
/ Tableau de bord — statistiques CDN par dossier
/browse/ Navigateur de fichiers — aperçu, suppression, upload
/search Recherche par nom / contenu / date
/stats/ Rapport de trafic GoAccess

Upload de fichiers

Dans le navigateur (/browse/), une zone de dépôt est affichée en bas de chaque dossier. Elle accepte plusieurs fichiers à la fois (glisser-déposer ou sélection). Les chemins protégés (.git, app, scripts, etc.) sont refusés avec 403.

Pour limiter la taille des uploads, ajouter dans app/app.py :

app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024  # 50 Mo

Variables d'environnement de l'app

Le fichier de référence est app/.env.example. Sur le serveur : /opt/static-cdn/.env.

Auth & Flask

Variable Obligatoire Description
SECRET_KEY oui Clé secrète Flask (chaîne aléatoire longue)
ALPID_CLIENT_ID oui Client Keycloak (static-cdn)
ALPID_CLIENT_SECRET oui Secret client Keycloak
ALPID_DISCOVERY_URL oui URL OIDC discovery AlpID
ADMIN_GROUPS non Groupes Keycloak autorisés (défaut : admins)
ADMIN_EMAILS non Fallback si le claim groups est absent du token
ASSETS_ROOT oui Racine du CDN (/var/www/clients/client1/web17/web en prod)

Stats GoAccess

Variable Description
STATS_FILE Rapport HTML GoAccess servi dans /stats/ (défaut : /opt/static-cdn/goaccess.html)
STATS_JSON Rapport JSON GoAccess pour les badges "Vues" (défaut : /opt/static-cdn/goaccess.json)
STATS_LOG_FILE Log Apache à analyser pour la génération à la demande
STATS_GENERATE_CMD Commande GoAccess complète — remplace la commande par défaut si renseigné

Génération du rapport GoAccess à la demande

Si goaccess.html est absent, la page /stats/ affiche un bouton Générer et ouvrir :

  1. Lance GoAccess en arrière-plan (thread daemon)
  2. Interroge /stats/status toutes les 2 s
  3. Ouvre le rapport dans un nouvel onglet dès qu'il est prêt

Si le rapport existe, un bouton ↗ Ouvrir dans un nouvel onglet l'affiche directement.

La commande par défaut (si STATS_GENERATE_CMD est vide) :

goaccess <STATS_LOG_FILE> --log-format=COMBINED -o <STATS_FILE> [-o <STATS_JSON>]

Valeurs utilisées sur le serveur :

STATS_LOG_FILE=/var/log/ispconfig/httpd/static.alpinux.org/access.log
STATS_GENERATE_CMD=goaccess /var/log/ispconfig/httpd/static.alpinux.org/access.log \
  --config-file=/var/log/ispconfig/httpd/static.alpinux.org/goaccess.conf \
  -o /opt/static-cdn/goaccess.html -o /opt/static-cdn/goaccess.json

Prérequis serveur : l'utilisateur abonnelc doit appartenir au groupe client1 pour lire les logs ISPConfig (opération à faire une seule fois) :

sudo usermod -a -G client1 abonnelc
sudo systemctl restart static-cdn

Première installation (nouveau serveur)

1. Créer le site dans ISPConfig

https://owni.alpinux.org:8080Sites → Ajouter un site web

  • Domaine : static.alpinux.org
  • Activer Let's Encrypt SSL
  • DocumentRoot : /var/www/clients/client1/web17/web

2. Configurer le proxy Apache

Dans ISPConfig → onglet Directives Apache SSL du site :

# CDN public → Apache sert directement depuis DocumentRoot
ProxyPass /logo/        !
ProxyPass /wiki/        !
ProxyPass /error/       !
ProxyPass /favicon.ico  !
ProxyPass /robots.txt   !

# Tableau de bord → Flask
RequestHeader set X-Forwarded-Proto "https"
ProxyPreserveHost On
ProxyPass        / http://127.0.0.1:5003/
ProxyPassReverse / http://127.0.0.1:5003/

3. Déployer l'app Flask

# Depuis la machine locale
./scripts/deploy-app.sh

# Sur le serveur — créer /opt/static-cdn/.env (voir app/.env.example)
ssh alpinux.org
nano /opt/static-cdn/.env

# Activer le service
sudo systemctl enable --now static-cdn

4. Pousser les assets CDN

./scripts/push-assets.sh -y

5. Droits sur les logs (pour la génération GoAccess)

sudo usermod -a -G client1 abonnelc
sudo systemctl restart static-cdn