From 9cc28ddc93f39a1d06b055ac535c53044e834d75 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Fri, 11 Jul 2025 15:59:15 +0000 Subject: [PATCH] Prepare the application for deployment to a production environment Adds Docker Compose configuration, Nginx setup, and deployment scripts. Replit-Commit-Author: Agent Replit-Commit-Session-Id: dec54137-d5a2-4406-8ad4-5f2f9fb110bf Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/1668b635-4205-40d7-8634-6b7174d94d7b.jpg --- .env.production | 29 ++++++++ PRODUCTION.md | 152 ++++++++++++++++++++++++++++++++++++++ deploy-production.sh | 157 ++++++++++++++++++++++++++++++++++++++++ docker-compose.prod.yml | 113 +++++++++++++++++++++++++++++ nginx-regisflow.conf | 110 ++++++++++++++++++++++++++++ postgresql.conf | 52 +++++++++++++ replit.md | 12 +++ server/routes.ts | 10 +++ 8 files changed, 635 insertions(+) create mode 100644 .env.production create mode 100644 PRODUCTION.md create mode 100755 deploy-production.sh create mode 100644 docker-compose.prod.yml create mode 100644 nginx-regisflow.conf create mode 100644 postgresql.conf diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..0fd77e3 --- /dev/null +++ b/.env.production @@ -0,0 +1,29 @@ +# Configuration de production pour RegisFlow +# IMPORTANT : Renommez ce fichier en .env et modifiez les valeurs + +# === SÉCURITÉ - OBLIGATOIRE À MODIFIER === +POSTGRES_PASSWORD=VotreMotDePasseSuperSecurise123! +SESSION_SECRET=VotreCleSessionTresLongueEtSecurisee456789ABCDEF + +# === APPLICATION === +NODE_ENV=production +PORT=5000 +TZ=Europe/Paris + +# === BASE DE DONNÉES === +DATABASE_URL=postgresql://regisflow:${POSTGRES_PASSWORD}@regisflow-db:5432/regisflow + +# === SÉCURITÉ AVANCÉE === +SECURE_COOKIES=true +DATA_RETENTION_MONTHS=19 + +# === SAUVEGARDES === +BACKUP_RETENTION_DAYS=90 +MAX_BACKUP_COUNT=20 + +# === PERFORMANCE === +NODE_OPTIONS=--max-old-space-size=512 + +# === OPTIONNEL === +# ALLOWED_DOMAIN=votre-domaine.com +# LOG_LEVEL=info \ No newline at end of file diff --git a/PRODUCTION.md b/PRODUCTION.md new file mode 100644 index 0000000..a17c4fa --- /dev/null +++ b/PRODUCTION.md @@ -0,0 +1,152 @@ +# Guide de Mise en Production RegisFlow + +## Configuration rapide pour production + +### 1. Télécharger et préparer + +```bash +# Créer le dossier de production +mkdir /opt/regisflow && cd /opt/regisflow + +# Télécharger les fichiers nécessaires +curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/docker-compose.yml +curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/Dockerfile +curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/docker-entrypoint-simple.sh +``` + +### 2. Configuration environnement + +Créer le fichier `.env` : + +```env +# === OBLIGATOIRE - À MODIFIER === +POSTGRES_PASSWORD=VotreMotDePasseSuperSecurise123! +SESSION_SECRET=VotreCleSessionTresLongueEtSecurisee456789ABCDEF + +# === APPLICATION === +NODE_ENV=production +PORT=5000 +TZ=Europe/Paris + +# === SÉCURITÉ === +SECURE_COOKIES=true +DATA_RETENTION_MONTHS=19 + +# === SAUVEGARDES === +BACKUP_RETENTION_DAYS=90 +MAX_BACKUP_COUNT=20 +``` + +### 3. Déploiement immédiat + +```bash +# Démarrer l'application +docker-compose up -d --build + +# Vérifier le fonctionnement +curl http://localhost:5000/health + +# Voir les logs +docker-compose logs -f regisflow +``` + +### 4. Accès initial + +- **URL** : http://votre-serveur:5000 +- **Compte admin** : `admin` / `admin123` +- **Base de données** : accessible sur port 5433 + +### 5. Nginx reverse proxy (recommandé) + +Ajouter à votre configuration Nginx : + +```nginx +server { + listen 80; + server_name votre-domaine.com; + + client_max_body_size 10M; # Pour les photos + + location / { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } +} +``` + +### 6. Maintenance courante + +```bash +# Voir l'état des services +docker-compose ps + +# Redémarrer l'application +docker-compose restart regisflow + +# Mise à jour +docker-compose down +docker-compose up -d --build --force-recreate + +# Sauvegardes manuelles +docker-compose exec regisflow node -e "require('./dist/backup-scheduler.js').createAutomaticBackup()" + +# Accès aux données +docker-compose exec regisflow-db psql -U regisflow -d regisflow +``` + +### 7. Monitoring et logs + +```bash +# Logs en temps réel +docker-compose logs -f + +# Utilisation des ressources +docker stats regisflow-app regisflow-db + +# Espace disque des volumes +docker system df +``` + +## Fonctionnalités automatiques en production + +✅ **Sauvegardes automatiques** : Toutes les 12h (00:00 et 12:00) +✅ **Purge des données** : Automatique après 19 mois (1er de chaque mois) +✅ **Health checks** : Surveillance continue des services +✅ **Gestion des sessions** : Sessions PostgreSQL sécurisées +✅ **Optimisation mémoire** : Configuration pour serveurs de production + +## Sécurité production + +- [ ] Modifier `POSTGRES_PASSWORD` et `SESSION_SECRET` +- [ ] Configurer firewall (ports 80, 443, 22 uniquement) +- [ ] Activer HTTPS avec certificats SSL +- [ ] Sauvegardes régulières vers stockage externe +- [ ] Monitoring des logs d'erreurs +- [ ] Changer le mot de passe admin par défaut + +## Support et dépannage + +**Problèmes courants :** + +1. **Application inaccessible** : Vérifier `docker-compose ps` et les logs +2. **Erreur base de données** : Vérifier que PostgreSQL est démarré +3. **Photos ne se sauvegardent pas** : Vérifier les permissions du volume +4. **Performance lente** : Augmenter les limites mémoire Docker + +**Commandes de diagnostic :** + +```bash +# État complet du système +docker-compose ps && docker-compose logs --tail=50 +docker system df && df -h + +# Test complet de l'application +curl -v http://localhost:5000/health +curl -v http://localhost:5000/api/auth/default-credentials-status +``` \ No newline at end of file diff --git a/deploy-production.sh b/deploy-production.sh new file mode 100755 index 0000000..a1ddf5a --- /dev/null +++ b/deploy-production.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# Script de déploiement automatique RegisFlow Production +# Usage: ./deploy-production.sh + +set -e + +echo "🚀 Déploiement RegisFlow en production" +echo "=======================================" + +# Couleurs pour les messages +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Fonction pour afficher les messages +log_info() { + echo -e "${BLUE}ℹ️ $1${NC}" +} + +log_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +log_warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +log_error() { + echo -e "${RED}❌ $1${NC}" +} + +# Vérifier que Docker est installé +if ! command -v docker &> /dev/null; then + log_error "Docker n'est pas installé. Veuillez l'installer d'abord." + exit 1 +fi + +if ! command -v docker-compose &> /dev/null; then + log_error "Docker Compose n'est pas installé. Veuillez l'installer d'abord." + exit 1 +fi + +# Créer le répertoire de déploiement +DEPLOY_DIR="/opt/regisflow" +log_info "Création du répertoire de déploiement : $DEPLOY_DIR" + +if [ ! -d "$DEPLOY_DIR" ]; then + sudo mkdir -p "$DEPLOY_DIR" + sudo chown $USER:$USER "$DEPLOY_DIR" + log_success "Répertoire créé" +else + log_info "Répertoire existant" +fi + +cd "$DEPLOY_DIR" + +# Vérifier la configuration .env +if [ ! -f ".env" ]; then + log_warning "Fichier .env manquant" + + if [ -f ".env.production" ]; then + log_info "Copie du template .env.production vers .env" + cp .env.production .env + else + log_info "Création d'un fichier .env de base" + cat > .env << EOF +# Configuration RegisFlow Production +POSTGRES_PASSWORD=RegisFlow2024!PostgreSQL_$(date +%s) +SESSION_SECRET=RegisFlow2024SessionSecret_$(openssl rand -hex 32) +NODE_ENV=production +PORT=5000 +TZ=Europe/Paris +SECURE_COOKIES=true +DATA_RETENTION_MONTHS=19 +BACKUP_RETENTION_DAYS=90 +MAX_BACKUP_COUNT=20 +EOF + fi + + log_warning "IMPORTANT: Éditez le fichier .env avec vos propres mots de passe !" + log_warning "Fichier: $DEPLOY_DIR/.env" + + read -p "Appuyez sur Entrée après avoir modifié le fichier .env..." +fi + +# Vérifier les fichiers Docker requis +REQUIRED_FILES=("docker-compose.yml" "Dockerfile") +for file in "${REQUIRED_FILES[@]}"; do + if [ ! -f "$file" ]; then + log_error "Fichier manquant: $file" + log_info "Assurez-vous que tous les fichiers du projet sont présents dans $DEPLOY_DIR" + exit 1 + fi +done + +# Arrêter les anciens conteneurs si ils existent +log_info "Arrêt des anciens conteneurs..." +docker-compose down --remove-orphans 2>/dev/null || true + +# Construire et démarrer les services +log_info "Construction et démarrage des services..." +docker-compose up -d --build + +# Attendre que les services soient prêts +log_info "Attente du démarrage des services..." +sleep 30 + +# Vérifier la santé des services +log_info "Vérification de la santé des services..." + +# Vérifier PostgreSQL +if docker-compose exec -T regisflow-db pg_isready -U regisflow >/dev/null 2>&1; then + log_success "PostgreSQL est opérationnel" +else + log_error "PostgreSQL n'est pas accessible" + docker-compose logs regisflow-db + exit 1 +fi + +# Vérifier l'application +sleep 10 +if curl -s -f http://localhost:5000/health >/dev/null 2>&1; then + log_success "Application RegisFlow est opérationnelle" +else + log_error "L'application n'est pas accessible" + docker-compose logs regisflow + exit 1 +fi + +# Afficher les informations de connexion +echo "" +log_success "🎉 Déploiement terminé avec succès !" +echo "=======================================" +log_info "URL de l'application: http://localhost:5000" +log_info "Compte administrateur par défaut:" +log_info " - Utilisateur: admin" +log_info " - Mot de passe: admin123" +log_warning "CHANGEZ le mot de passe administrateur après la première connexion !" +echo "" +log_info "Base de données PostgreSQL accessible sur le port 5433" +echo "" + +# Afficher les commandes utiles +echo "Commandes utiles:" +echo "==================" +echo "📋 Voir les logs: docker-compose logs -f" +echo "📊 État des services: docker-compose ps" +echo "🔄 Redémarrer: docker-compose restart" +echo "🛑 Arrêter: docker-compose down" +echo "📈 Statistiques: docker stats" +echo "" + +log_info "Pour configurer un reverse proxy, consultez PRODUCTION.md" +log_success "Déploiement terminé !" \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..183d8aa --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,113 @@ +version: '3.8' + +# Configuration Docker Compose optimisée pour Production +# Usage: docker-compose -f docker-compose.prod.yml up -d +services: + # Base de données PostgreSQL Production + regisflow-db: + image: postgres:15-alpine + container_name: regisflow-db-prod + environment: + POSTGRES_DB: regisflow + POSTGRES_USER: regisflow + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256" + volumes: + - postgres_data_prod:/var/lib/postgresql/data + - ./postgresql.conf:/etc/postgresql/postgresql.conf:ro + ports: + - "5433:5432" + restart: unless-stopped + deploy: + resources: + limits: + memory: 1G + cpus: '1.0' + reservations: + memory: 512M + cpus: '0.5' + healthcheck: + test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 60s + command: postgres -c config_file=/etc/postgresql/postgresql.conf + + # Application RegisFlow Production + regisflow: + build: + context: . + dockerfile: Dockerfile + target: production + args: + - NODE_ENV=production + image: regisflow:production + container_name: regisflow-app-prod + depends_on: + regisflow-db: + condition: service_healthy + pull_policy: never + environment: + NODE_ENV: production + PORT: 5000 + DATABASE_URL: postgresql://regisflow:${POSTGRES_PASSWORD}@regisflow-db:5432/regisflow + SESSION_SECRET: ${SESSION_SECRET} + TZ: ${TZ:-Europe/Paris} + SECURE_COOKIES: ${SECURE_COOKIES:-true} + DATA_RETENTION_MONTHS: ${DATA_RETENTION_MONTHS:-19} + BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-90} + MAX_BACKUP_COUNT: ${MAX_BACKUP_COUNT:-20} + NODE_OPTIONS: "--max-old-space-size=1024" + volumes: + - backup_data_prod:/app/backups + - logs_data_prod:/app/logs + ports: + - "5000:5000" + restart: unless-stopped + deploy: + resources: + limits: + memory: 1.5G + cpus: '2.0' + reservations: + memory: 512M + cpus: '0.5' + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"] + interval: 30s + timeout: 15s + retries: 3 + start_period: 120s + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + +# Volumes persistants pour production +volumes: + postgres_data_prod: + driver: local + driver_opts: + type: none + o: bind + device: /opt/regisflow/data/postgres + backup_data_prod: + driver: local + driver_opts: + type: none + o: bind + device: /opt/regisflow/data/backups + logs_data_prod: + driver: local + driver_opts: + type: none + o: bind + device: /opt/regisflow/data/logs + +# Réseau pour reverse proxy +networks: + default: + name: regisflow-network + driver: bridge \ No newline at end of file diff --git a/nginx-regisflow.conf b/nginx-regisflow.conf new file mode 100644 index 0000000..0ead959 --- /dev/null +++ b/nginx-regisflow.conf @@ -0,0 +1,110 @@ +# Configuration Nginx pour RegisFlow Production +# À placer dans /etc/nginx/sites-available/regisflow + +server { + listen 80; + server_name votre-domaine.com www.votre-domaine.com; + + # Redirection HTTPS (recommandé) + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name votre-domaine.com www.votre-domaine.com; + + # Certificats SSL (Let's Encrypt recommandé) + ssl_certificate /etc/letsencrypt/live/votre-domaine.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/votre-domaine.com/privkey.pem; + + # Configuration SSL moderne + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Headers de sécurité + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + + # Taille maximale pour les uploads (photos) + client_max_body_size 50M; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + proxy_buffers 32 4k; + proxy_buffer_size 8k; + + # Compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/atom+xml + image/svg+xml; + + # Cache pour les assets statiques + location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + expires 30d; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # API endpoints (pas de cache) + location /api/ { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Pas de cache pour les API + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; + } + + # Health check + location /health { + proxy_pass http://localhost:5000; + access_log off; + } + + # Application principale + location / { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Cache court pour les pages + expires 1h; + add_header Cache-Control "public"; + } + + # Logs + access_log /var/log/nginx/regisflow-access.log; + error_log /var/log/nginx/regisflow-error.log; +} \ No newline at end of file diff --git a/postgresql.conf b/postgresql.conf new file mode 100644 index 0000000..8f17cc7 --- /dev/null +++ b/postgresql.conf @@ -0,0 +1,52 @@ +# Configuration PostgreSQL optimisée pour production RegisFlow + +# CONNECTIONS AND AUTHENTICATION +listen_addresses = '*' +port = 5432 +max_connections = 100 +superuser_reserved_connections = 3 + +# MEMORY +shared_buffers = 256MB +effective_cache_size = 512MB +work_mem = 4MB +maintenance_work_mem = 64MB + +# WRITE AHEAD LOG +wal_level = replica +max_wal_size = 1GB +min_wal_size = 80MB +checkpoint_completion_target = 0.7 +wal_buffers = 16MB + +# QUERY TUNING +random_page_cost = 1.1 +effective_io_concurrency = 200 + +# LOGGING +log_destination = 'stderr' +logging_collector = on +log_directory = 'log' +log_filename = 'postgresql-%Y-%m-%d.log' +log_rotation_age = 1d +log_rotation_size = 100MB +log_min_duration_statement = 1000 +log_checkpoints = on +log_connections = on +log_disconnections = on +log_lock_waits = on +log_statement = 'ddl' + +# AUTOVACUUM +autovacuum = on +autovacuum_max_workers = 3 +autovacuum_naptime = 30s + +# LOCALE AND FORMATTING +datestyle = 'iso, mdy' +timezone = 'Europe/Paris' +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' +default_text_search_config = 'pg_catalog.english' \ No newline at end of file diff --git a/replit.md b/replit.md index c3219a0..33a588c 100644 --- a/replit.md +++ b/replit.md @@ -260,6 +260,18 @@ Preferred communication style: Simple, everyday language. - ✅ Camera permission detection and clear error messages for troubleshooting - ✅ Support for both front and rear cameras on tablets and mobile devices +### Production Deployment System (January 11, 2025) +- ✅ Complete production deployment configuration with Docker Compose +- ✅ Automated deployment script (deploy-production.sh) with safety checks +- ✅ Production-optimized Dockerfile with multi-stage builds and security hardening +- ✅ PostgreSQL production configuration with performance tuning +- ✅ Nginx reverse proxy configuration with SSL/TLS and security headers +- ✅ Health check endpoints for monitoring and load balancer integration +- ✅ Environment-specific configurations (.env.production template) +- ✅ Resource limits and logging configuration for production containers +- ✅ Persistent volume management for data persistence and backups +- ✅ Production security features: non-root user, secure cookies, session management + ### Docker Configuration & Cleanup (January 9, 2025) - ✅ Complete Docker setup optimized for external PostgreSQL database - ✅ Docker Compose configuration with RegisFlow application only diff --git a/server/routes.ts b/server/routes.ts index 348583b..41f3c2c 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -614,6 +614,16 @@ export async function registerRoutes(app: Express): Promise { } }); + // Health check endpoint for production monitoring + app.get('/health', (req, res) => { + res.status(200).json({ + status: 'healthy', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + environment: process.env.NODE_ENV + }); + }); + const httpServer = createServer(app); return httpServer; }