Add secure admin panel with authentication and authorization features, update DEX.md to include admin panel documentation, and modify INSTALL_ROCKY.md to include ADMIN_SECRET configuration. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 923ae0e3-a363-4db8-b04a-e8baca2a1330 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 79c67b0b-a0eb-4a65-acef-813c12178ea4 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8af7d2ec-2cc3-4ece-8af3-9f071488d072/923ae0e3-a363-4db8-b04a-e8baca2a1330/sVU8w5x Replit-Helium-Checkpoint-Created: true
12 KiB
Installation sur RockyLinux — La Voix du Peuple
Cible : VM RockyLinux 9.x
Port public : HTTP 8080 (vous gérez le HTTPS en amont)
Port interne : Gunicorn 8000 (localhost uniquement)
Répertoire d'installation : /opt/voix-du-peuple
Utilisateur système : voixdupeuple
Table des matières
- Prérequis
- Préparation du serveur
- Installation des paquets
- Utilisateur système
- Clonage du dépôt
- Base de données PostgreSQL
- Environnement Python
- Configuration du domaine et variables d'environnement
- Build du frontend
- Service Gunicorn (systemd)
- Nginx
- Firewall
- Vérification finale
- Disaster Recovery
- Maintenance et mises à jour
1. Prérequis
- VM RockyLinux 9.x avec accès root (ou sudo)
- 1 vCPU minimum, 1 Go RAM (2 Go recommandés)
- 10 Go de disque
- Accès réseau sortant (pour cloner le dépôt et télécharger les paquets)
- Nom de domaine configuré (enregistrement DNS A pointant vers l'IP de la VM)
- Clé SSH ou accès console
2. Préparation du serveur
# Mise à jour complète du système
dnf update -y
# Outils de base
dnf install -y curl wget git tar unzip vim
# Activer le dépôt EPEL (nécessaire pour certains paquets)
dnf install -y epel-release
3. Installation des paquets
Python 3.11
dnf install -y python3.11 python3.11-pip python3.11-devel
python3.11 --version # doit afficher 3.11.x
Node.js 20 et pnpm
# Dépôt Node.js 20 LTS
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
dnf install -y nodejs
# pnpm
npm install -g pnpm
pnpm --version
node --version # doit afficher 20.x
PostgreSQL 15
# Dépôt officiel PostgreSQL
dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
dnf -qy module disable postgresql
dnf install -y postgresql15-server postgresql15
# Initialisation et démarrage
postgresql-15-setup initdb
systemctl enable postgresql-15
systemctl start postgresql-15
systemctl status postgresql-15 # doit afficher "active (running)"
Nginx
dnf install -y nginx
systemctl enable nginx
4. Utilisateur système
# Créer un utilisateur dédié sans shell de connexion
useradd -r -s /sbin/nologin -d /opt/voix-du-peuple voixdupeuple
# Répertoire de logs
mkdir -p /var/log/voix-du-peuple
chown voixdupeuple:voixdupeuple /var/log/voix-du-peuple
5. Clonage du dépôt
# Créer le répertoire d'installation
mkdir -p /opt/voix-du-peuple
cd /opt/voix-du-peuple
# Cloner depuis votre Gitea
git clone https://homegit.gyozamancave.fr/billisdead/la-voix-du-peuple.git .
# (ou via SSH si une clé est configurée sur votre serveur Gitea)
# Rendre le répertoire accessible à l'utilisateur système
chown -R voixdupeuple:voixdupeuple /opt/voix-du-peuple
6. Base de données PostgreSQL
# Se connecter en tant que postgres
su - postgres
# Créer l'utilisateur et la base
psql <<EOF
CREATE USER voix_user WITH PASSWORD 'MOT_DE_PASSE_FORT';
CREATE DATABASE voix_du_peuple OWNER voix_user;
GRANT ALL PRIVILEGES ON DATABASE voix_du_peuple TO voix_user;
EOF
exit # revenir à root
Tester la connexion :
psql -U voix_user -d voix_du_peuple -h 127.0.0.1 -c '\l'
7. Environnement Python
cd /opt/voix-du-peuple
# Créer le virtualenv
python3.11 -m venv .venv
# Installer les dépendances
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -r artifacts/flask-api/requirements.txt
8. Configuration du domaine et variables d'environnement
8.1 Créer le fichier .env
cp .env.example .env # si le fichier exemple existe, sinon créer manuellement
vim .env
Contenu minimal du .env :
# Base de données
DATABASE_URL=postgresql://voix_user:MOT_DE_PASSE_FORT@127.0.0.1:5432/voix_du_peuple
# IA Mistral
MISTRAL_API_KEY=votre_cle_mistral_ici
# Sécurité Flask
SESSION_SECRET=generez-une-chaine-aleatoire-longue-ici
# Panel admin — mot de passe de connexion à /admin (OBLIGATOIRE)
ADMIN_SECRET=choisissez-un-mot-de-passe-long-et-complexe-ici
# Modèles IA (valeurs par défaut si omis)
# FILTER_MODEL=mistral-small-latest
# SYNTHESIS_MODEL=mistral-large-latest
# Domaine public — utilisé par le QR code du flyer
VITE_APP_URL=https://votredomaine.fr
Générer SESSION_SECRET et ADMIN_SECRET :
python3 -c "import secrets; print(secrets.token_hex(32))"
# Exécuter deux fois pour obtenir deux valeurs distinctes
8.2 Changer le domaine (QR code)
Le flyer génère automatiquement son QR code à partir de VITE_APP_URL. Pour changer le domaine :
# Depuis /opt/voix-du-peuple
bash scripts/set-domain.sh https://votredomaine.fr
Ce script met à jour VITE_APP_URL dans .env et reconstruit le frontend.
Appliquer ensuite : systemctl reload nginx
9. Build du frontend
cd /opt/voix-du-peuple
# Installer les dépendances Node
pnpm install
# Construire le frontend (lit VITE_APP_URL depuis .env)
source .env
export VITE_APP_URL
pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts
# Vérifier que le build est présent
ls artifacts/voix-du-peuple/dist/public/
10. Service Gunicorn (systemd)
# Copier le fichier de service
cp deploy/voix-du-peuple-api.service /etc/systemd/system/
# Recharger systemd et activer le service
systemctl daemon-reload
systemctl enable voix-du-peuple-api
systemctl start voix-du-peuple-api
systemctl status voix-du-peuple-api
Vérifier que Gunicorn écoute bien sur le port interne :
ss -tlnp | grep 8000
# doit afficher : 127.0.0.1:8000
Tester l'API directement :
curl http://127.0.0.1:8000/health
# réponse attendue : {"status": "ok"}
11. Nginx
11.1 Installer la configuration
# Copier la config fournie
cp deploy/nginx.conf /etc/nginx/conf.d/voix-du-peuple.conf
# (Optionnel) Ajuster le nom de serveur dans la config
vim /etc/nginx/conf.d/voix-du-peuple.conf
# Modifier : server_name _;
# En : server_name votredomaine.fr;
# Tester la configuration
nginx -t
# Démarrer Nginx
systemctl start nginx
systemctl status nginx
11.2 Vérifier que Nginx écoute sur 8080
ss -tlnp | grep 8080
# doit afficher : 0.0.0.0:8080
12. Firewall
# Autoriser le port 8080 (HTTP)
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
# Vérifier
firewall-cmd --list-ports
Le port 8000 (Gunicorn) ne doit PAS être ouvert — il n'est accessible que depuis localhost via Nginx.
13. Vérification finale
# Health check API (via Nginx)
curl http://localhost:8080/health
# {"status": "ok"}
# Page principale
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/
# 200
# Depuis l'extérieur (remplacer par l'IP de votre VM)
curl http://IP_DE_LA_VM:8080/health
Checklist :
systemctl status postgresql-15→ activesystemctl status voix-du-peuple-api→ activesystemctl status nginx→ activecurl http://localhost:8080/health→{"status":"ok"}- L'interface s'affiche dans le navigateur sur
http://IP:8080 - Le flyer
/flyeraffiche le bon nom de domaine dans le QR code
14. Disaster Recovery
14.1 Sauvegarde de la base de données
# Dump complet (à planifier via cron)
pg_dump -U voix_user -h 127.0.0.1 voix_du_peuple > /opt/backups/voix_$(date +%Y%m%d_%H%M).sql
# Automatiser avec cron (tous les jours à 3h)
crontab -e
# Ajouter :
# 0 3 * * * pg_dump -U voix_user -h 127.0.0.1 voix_du_peuple > /opt/backups/voix_$(date +\%Y\%m\%d).sql
mkdir -p /opt/backups
14.2 Restauration de la base de données
# Stopper l'API pendant la restauration
systemctl stop voix-du-peuple-api
# Vider et restaurer la base
psql -U voix_user -h 127.0.0.1 voix_du_peuple -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
psql -U voix_user -h 127.0.0.1 voix_du_peuple < /opt/backups/voix_20260401.sql
# Redémarrer
systemctl start voix-du-peuple-api
14.3 Réinstallation complète depuis zéro
Si la VM est perdue, répéter les étapes 1 à 13 puis restaurer la base depuis le dernier backup :
psql -U voix_user -h 127.0.0.1 voix_du_peuple < /opt/backups/voix_DERNIER.sql
Les backups doivent être stockés hors de la VM (NFS, S3, objet distant…).
14.4 Rollback de code
cd /opt/voix-du-peuple
# Voir l'historique des commits
git log --oneline -10
# Revenir à un commit précédent
git checkout <COMMIT_HASH>
# Reconstruire le frontend si nécessaire
bash scripts/set-domain.sh https://votredomaine.fr
# Redémarrer l'API
systemctl restart voix-du-peuple-api
systemctl reload nginx
14.5 En cas de service hors ligne
# Diagnostic rapide
systemctl status voix-du-peuple-api
journalctl -u voix-du-peuple-api -n 50
systemctl status nginx
journalctl -u nginx -n 20
systemctl status postgresql-15
# Relance forcée
systemctl restart voix-du-peuple-api
systemctl restart nginx
15. Maintenance et mises à jour
15.1 Mise à jour du code
cd /opt/voix-du-peuple
# Récupérer les derniers commits depuis Gitea
git pull origin main
# Si les dépendances Python ont changé (requirements.txt modifié)
.venv/bin/pip install -r artifacts/flask-api/requirements.txt
# Si les dépendances Node ont changé (package.json modifié)
pnpm install
# Reconstruire le frontend (toujours faire après un pull)
source .env && export VITE_APP_URL
pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts
# Appliquer
systemctl restart voix-du-peuple-api
systemctl reload nginx
15.2 Changer de nom de domaine
cd /opt/voix-du-peuple
bash scripts/set-domain.sh https://nouveaudomaine.fr
systemctl reload nginx
Le QR code est régénéré automatiquement dans le build.
15.3 Changer la clé API Mistral
vim /opt/voix-du-peuple/.env
# Modifier MISTRAL_API_KEY
systemctl restart voix-du-peuple-api
15.4 Purger les contributions
psql -U voix_user -h 127.0.0.1 voix_du_peuple
-- Tout purger (irréversible sans backup)
TRUNCATE ideas;
TRUNCATE synthesis;
-- Supprimer seulement les refusées
DELETE FROM ideas WHERE accepted = false;
-- Forcer une re-synthèse au prochain envoi
DELETE FROM synthesis;
15.5 Consulter les logs
# Logs de l'API en temps réel
journalctl -u voix-du-peuple-api -f
# Logs d'accès Gunicorn
tail -f /var/log/voix-du-peuple/api-access.log
# Logs d'erreur Gunicorn
tail -f /var/log/voix-du-peuple/api-error.log
# Logs Nginx
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
15.6 Rotation des logs
# Créer un fichier logrotate
cat > /etc/logrotate.d/voix-du-peuple <<EOF
/var/log/voix-du-peuple/*.log {
daily
rotate 14
compress
missingok
notifempty
postrotate
systemctl kill -s USR1 voix-du-peuple-api
endscript
}
EOF
15.7 Vérification de santé (cron)
# Ajouter un health check toutes les 5 minutes
crontab -e
# Ajouter :
# */5 * * * * curl -sf http://127.0.0.1:8080/health || systemctl restart voix-du-peuple-api
15.8 Tableau de bord des commandes rapides
| Opération | Commande |
|---|---|
| Statut global | systemctl status voix-du-peuple-api nginx postgresql-15 |
| Relancer l'API | systemctl restart voix-du-peuple-api |
| Recharger Nginx | systemctl reload nginx |
| Logs API live | journalctl -u voix-du-peuple-api -f |
| Mise à jour complète | git pull && bash scripts/set-domain.sh $VITE_APP_URL && systemctl restart voix-du-peuple-api && systemctl reload nginx |
| Changer de domaine | bash scripts/set-domain.sh https://domaine.fr |
| Backup BDD | pg_dump -U voix_user -h 127.0.0.1 voix_du_peuple > backup.sql |
| Purger les données | psql -U voix_user -h 127.0.0.1 voix_du_peuple -c "TRUNCATE ideas; TRUNCATE synthesis;" |
| Health check | curl http://127.0.0.1:8080/health |