App Flask complète pour https://dynamic.alpinux.org : - 10 quiz Linux, 5 niveaux (Découverte → Expert), 50+ questions - Public : Découverte, Débutant, Intermédiaire (6 quiz) - Membres AlpID : Avancé, Expert (4 quiz — Git, Admin, Sécurité, Bash) - Navigation question par question avec avance automatique après choix - Score calculé côté serveur, enregistré en SQLite si connecté - Page profil : meilleurs scores par quiz + historique des tentatives Authentification : - OIDC via authlib + AlpID (Keycloak), SSO partagé avec Gitea/Nextcloud - Décorateur @login_required, redirection post-login sur l'URL d'origine - /auth/login, /auth/callback, /auth/logout Structure : - dynamic/app.py, db.py, quiz.py, auth_utils.py - dynamic/routes/ (public.py, auth.py, protected.py) - dynamic/templates/ (base, index, quiz/*, profil/) - dynamic/static/ (style.css thème Alpinux, quiz.js vanilla) - dynamic/data/quizzes.json (source de vérité des questions) - dynamic/.env.example Infrastructure : - scripts/dynamic.alpinux.org.vhost.conf (Apache reverse proxy) - scripts/dynamic.alpinux.org.service (systemd Gunicorn) - docs/technique/deploiement-dynamic.md (procédure complète) - mkdocs.yml : page de déploiement ajoutée à la nav Technique - .gitignore : exclut venv/ et .env Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
24 lines
682 B
Desktop File
24 lines
682 B
Desktop File
# Systemd unit pour l'app Flask dynamic.alpinux.org
|
|
# Copier dans /etc/systemd/system/dynamic-alpinux.service
|
|
# puis : sudo systemctl enable --now dynamic-alpinux
|
|
|
|
[Unit]
|
|
Description=Alpinux Dynamic — Quiz interactifs (Flask + Gunicorn)
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=alpinux
|
|
Group=alpinux
|
|
WorkingDirectory=/home/alpinux/dynamic
|
|
EnvironmentFile=/etc/dynamic-alpinux/config.env
|
|
ExecStart=/home/alpinux/dynamic/venv/bin/gunicorn \
|
|
--workers 2 \
|
|
--bind 127.0.0.1:5001 \
|
|
--access-logfile /var/log/dynamic-alpinux/access.log \
|
|
--error-logfile /var/log/dynamic-alpinux/error.log \
|
|
app:app
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|