e279dab70a
Add a detailed guide for installing the application on Rocky Linux, including systemd service setup and Nginx configuration. Streamline domain setting by introducing a script to update environment variables and rebuild the frontend, and remove the URL input from the flyer component. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 923ae0e3-a363-4db8-b04a-e8baca2a1330 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 3d999b96-66af-4728-92b9-3a39ade05f44 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8af7d2ec-2cc3-4ece-8af3-9f071488d072/923ae0e3-a363-4db8-b04a-e8baca2a1330/qCk7LE3 Replit-Helium-Checkpoint-Created: true
539 lines
12 KiB
Markdown
539 lines
12 KiB
Markdown
# 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
|
|
|
|
1. [Prérequis](#1-prérequis)
|
|
2. [Préparation du serveur](#2-préparation-du-serveur)
|
|
3. [Installation des paquets](#3-installation-des-paquets)
|
|
4. [Utilisateur système](#4-utilisateur-système)
|
|
5. [Clonage du dépôt](#5-clonage-du-dépôt)
|
|
6. [Base de données PostgreSQL](#6-base-de-données-postgresql)
|
|
7. [Environnement Python](#7-environnement-python)
|
|
8. [Configuration du domaine et variables d'environnement](#8-configuration-du-domaine-et-variables-denvironnement)
|
|
9. [Build du frontend](#9-build-du-frontend)
|
|
10. [Service Gunicorn (systemd)](#10-service-gunicorn-systemd)
|
|
11. [Nginx](#11-nginx)
|
|
12. [Firewall](#12-firewall)
|
|
13. [Vérification finale](#13-vérification-finale)
|
|
14. [Disaster Recovery](#14-disaster-recovery)
|
|
15. [Maintenance et mises à jour](#15-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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
dnf install -y python3.11 python3.11-pip python3.11-devel
|
|
python3.11 --version # doit afficher 3.11.x
|
|
```
|
|
|
|
### Node.js 20 et pnpm
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
dnf install -y nginx
|
|
systemctl enable nginx
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Utilisateur système
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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 :
|
|
|
|
```bash
|
|
psql -U voix_user -d voix_du_peuple -h 127.0.0.1 -c '\l'
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Environnement Python
|
|
|
|
```bash
|
|
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`
|
|
|
|
```bash
|
|
cp .env.example .env # si le fichier exemple existe, sinon créer manuellement
|
|
vim .env
|
|
```
|
|
|
|
Contenu minimal du `.env` :
|
|
|
|
```bash
|
|
# 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
|
|
|
|
# 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 un SESSION_SECRET :
|
|
|
|
```bash
|
|
python3 -c "import secrets; print(secrets.token_hex(32))"
|
|
```
|
|
|
|
### 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 :
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
# 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 :
|
|
|
|
```bash
|
|
ss -tlnp | grep 8000
|
|
# doit afficher : 127.0.0.1:8000
|
|
```
|
|
|
|
Tester l'API directement :
|
|
|
|
```bash
|
|
curl http://127.0.0.1:8000/health
|
|
# réponse attendue : {"status": "ok"}
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Nginx
|
|
|
|
### 11.1 Installer la configuration
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
ss -tlnp | grep 8080
|
|
# doit afficher : 0.0.0.0:8080
|
|
```
|
|
|
|
---
|
|
|
|
## 12. Firewall
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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` → active
|
|
- [ ] `systemctl status voix-du-peuple-api` → active
|
|
- [ ] `systemctl status nginx` → active
|
|
- [ ] `curl http://localhost:8080/health` → `{"status":"ok"}`
|
|
- [ ] L'interface s'affiche dans le navigateur sur `http://IP:8080`
|
|
- [ ] Le flyer `/flyer` affiche le bon nom de domaine dans le QR code
|
|
|
|
---
|
|
|
|
## 14. Disaster Recovery
|
|
|
|
### 14.1 Sauvegarde de la base de données
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
```bash
|
|
mkdir -p /opt/backups
|
|
```
|
|
|
|
### 14.2 Restauration de la base de données
|
|
|
|
```bash
|
|
# 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 :
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
vim /opt/voix-du-peuple/.env
|
|
# Modifier MISTRAL_API_KEY
|
|
|
|
systemctl restart voix-du-peuple-api
|
|
```
|
|
|
|
### 15.4 Purger les contributions
|
|
|
|
```bash
|
|
psql -U voix_user -h 127.0.0.1 voix_du_peuple
|
|
```
|
|
|
|
```sql
|
|
-- 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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` |
|