diff --git a/.env.example b/.env.example index 347abd5..73a3aed 100644 --- a/.env.example +++ b/.env.example @@ -1,32 +1,66 @@ -# Configuration de l'environnement pour RegisFlow -# Copiez ce fichier en .env et modifiez les valeurs selon vos besoins +# Configuration de l'environnement pour RegisFlow - PRODUCTION +# Copiez ce fichier en .env et modifiez les valeurs OBLIGATOIRES pour la production -# Configuration de la base de données (DOCKER INTERNE) -# PRÉCONFIGURÉE - PostgreSQL et RegisFlow dans Docker -# Communication via nom de container : regisflow-db:5432 +# ========================================== +# CONFIGURATION POSTGRESQL (SÉCURISÉE) +# ========================================== +# OBLIGATOIRE: Changez ce mot de passe pour la production +POSTGRES_PASSWORD=CHANGEZ_MOI_EN_PRODUCTION_2024! -# Configuration PostgreSQL -POSTGRES_PASSWORD=RegisFlow2024! - -# Configuration automatique (NE PAS CHANGER) : -# - Container PostgreSQL : regisflow-db -# - Utilisateur: regisflow -# - Mot de passe: RegisFlow2024! -# - Base de données: regisflow +# Configuration automatique PostgreSQL : +# - Container: regisflow-db +# - Utilisateur: regisflow +# - Base de données: regisflow # - Port interne: 5432 (communication Docker) # - Port externe: 5433 (accès depuis l'hôte) -# Configuration de l'application +# ========================================== +# CONFIGURATION APPLICATION +# ========================================== NODE_ENV=production PORT=5000 -# Clé secrète pour les sessions (IMPORTANT: Changez cette valeur en production) -SESSION_SECRET=your-super-secret-session-key-change-in-production +# OBLIGATOIRE: Générez une clé secrète forte pour les sessions +# Exemple: openssl rand -base64 32 +SESSION_SECRET=CHANGEZ_MOI_GENERER_UNE_CLE_SECRETE_FORTE -# Configuration du timezone +# ========================================== +# CONFIGURATION SYSTÈME +# ========================================== +# Timezone pour les logs et planifications TZ=Europe/Paris -# Note: L'application sera accessible sur http://localhost:5000 après le démarrage -# Configuration optionnelle pour les sauvegardes -BACKUP_RETENTION_DAYS=30 -MAX_BACKUP_COUNT=10 \ No newline at end of file +# Configuration des sauvegardes automatiques +BACKUP_RETENTION_DAYS=90 +MAX_BACKUP_COUNT=20 + +# Configuration de la purge automatique (19 mois réglementaire) +DATA_RETENTION_MONTHS=19 + +# ========================================== +# SÉCURITÉ PRODUCTION +# ========================================== +# Activer les cookies sécurisés (nécessite HTTPS) +SECURE_COOKIES=true + +# Domaine autorisé pour l'application (optionnel) +# ALLOWED_DOMAIN=votre-domaine.com + +# ========================================== +# INSTRUCTIONS IMPORTANTES +# ========================================== +# 1. CHANGEZ OBLIGATOIREMENT : +# - POSTGRES_PASSWORD +# - SESSION_SECRET +# +# 2. Pour générer SESSION_SECRET : +# openssl rand -base64 32 +# +# 3. Pour HTTPS en production : +# - Configurez un reverse proxy (Nginx/Apache) +# - Obtenez un certificat SSL (Let's Encrypt) +# - Activez SECURE_COOKIES=true +# +# 4. Application accessible sur : +# - RegisFlow: http://localhost:5000 +# - PostgreSQL: localhost:5433 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 5ac5def..328e752 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,80 @@ -# Dockerfile pour RegisFlow -FROM node:18-alpine +# Dockerfile multi-stage pour RegisFlow Production +# Stage 1: Build +FROM node:18-alpine AS builder -# Installer les dépendances système nécessaires -RUN apk add --no-cache dumb-init postgresql-client wget python3 make g++ +# Installer les dépendances de build +RUN apk add --no-cache python3 make g++ -# Créer un utilisateur non-root -RUN addgroup -g 1001 -S nodejs -RUN adduser -S regisflow -u 1001 - -# Créer le répertoire de l'application -WORKDIR /app +# Créer le répertoire de build +WORKDIR /build # Copier les fichiers de dépendances COPY package*.json ./ -# Installer toutes les dépendances -RUN npm ci && npm cache clean --force +# Installer toutes les dépendances (dev + prod) +RUN npm ci --include=dev # Copier le code source -COPY --chown=regisflow:nodejs . . +COPY . . -# Copier le script d'entrée +# Construire l'application +RUN npm run build + +# Stage 2: Production +FROM node:18-alpine AS production + +# Installer uniquement les dépendances système nécessaires pour production +RUN apk add --no-cache \ + dumb-init \ + postgresql-client \ + wget \ + curl \ + && rm -rf /var/cache/apk/* + +# Créer un utilisateur non-root avec des permissions limitées +RUN addgroup -g 1001 -S nodejs && \ + adduser -S regisflow -u 1001 -G nodejs + +# Créer les répertoires avec permissions appropriées +WORKDIR /app +RUN mkdir -p /app/backups /app/logs /app/data && \ + chown -R regisflow:nodejs /app + +# Copier uniquement les fichiers nécessaires depuis le builder +COPY --from=builder --chown=regisflow:nodejs /build/package*.json ./ +COPY --from=builder --chown=regisflow:nodejs /build/dist ./dist +COPY --from=builder --chown=regisflow:nodejs /build/shared ./shared +COPY --from=builder --chown=regisflow:nodejs /build/drizzle.config.ts ./ + +# Installer uniquement les dépendances de production +RUN npm ci --only=production && \ + npm cache clean --force && \ + rm -rf /tmp/* + +# Copier les scripts de configuration COPY --chown=regisflow:nodejs docker-entrypoint.sh /usr/local/bin/ +COPY --chown=regisflow:nodejs postgres-prod.conf ./ RUN chmod +x /usr/local/bin/docker-entrypoint.sh -# Créer les répertoires nécessaires -RUN mkdir -p /app/backups && chown regisflow:nodejs /app/backups - # Changer vers l'utilisateur non-root USER regisflow # Exposer le port EXPOSE 5000 -# Variables d'environnement par défaut +# Variables d'environnement de production ENV NODE_ENV=production ENV PORT=5000 +ENV NODE_OPTIONS="--max-old-space-size=512" + +# Labels pour la documentation +LABEL maintainer="RegisFlow Team" +LABEL version="1.0.0" +LABEL description="Application RegisFlow pour la gestion des ventes de feux d'artifice" + +# Health check amélioré +HEALTHCHECK --interval=30s --timeout=15s --start-period=90s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1 # Utiliser dumb-init pour gérer les signaux ENTRYPOINT ["dumb-init", "--"] diff --git a/deploy-prod.sh b/deploy-prod.sh new file mode 100755 index 0000000..4ab040c --- /dev/null +++ b/deploy-prod.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +# Script de déploiement PRODUCTION RegisFlow +# Utilisation: ./deploy-prod.sh + +set -e + +echo "🚀 Déploiement PRODUCTION RegisFlow" +echo "====================================" + +# Vérifications préalables +echo "🔍 Vérifications préalables..." + +# Vérifier que nous sommes en mode production +if [ "$NODE_ENV" != "production" ]; then + echo "⚠️ Variable NODE_ENV non définie sur 'production'" + read -p "Continuer quand même ? (y/N): " -r + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Vérifier Docker et Docker Compose +if ! command -v docker &> /dev/null; then + echo "❌ Docker n'est pas installé" + exit 1 +fi + +if ! command -v docker-compose &> /dev/null; then + echo "❌ Docker Compose n'est pas installé" + exit 1 +fi + +# Créer les répertoires de données +echo "📁 Création des répertoires de données..." +mkdir -p data/{postgres,backups,logs,postgres-logs} +chmod 755 data data/* + +# Créer le fichier .env s'il n'existe pas +if [ ! -f .env ]; then + echo "📝 Création du fichier .env de production..." + cp .env.example .env + + echo "" + echo "⚠️ CONFIGURATION OBLIGATOIRE POUR LA PRODUCTION :" + echo " 1. Éditez le fichier .env" + echo " 2. Changez OBLIGATOIREMENT :" + echo " - POSTGRES_PASSWORD" + echo " - SESSION_SECRET" + echo " 3. Pour générer SESSION_SECRET :" + echo " openssl rand -base64 32" + echo "" + read -p "Appuyez sur Entrée après avoir configuré .env..." +fi + +# Vérifier les variables critiques +echo "🔒 Vérification de la configuration de sécurité..." +source .env + +if [ "$POSTGRES_PASSWORD" = "CHANGEZ_MOI_EN_PRODUCTION_2024!" ]; then + echo "❌ POSTGRES_PASSWORD doit être changé pour la production !" + exit 1 +fi + +if [ "$SESSION_SECRET" = "CHANGEZ_MOI_GENERER_UNE_CLE_SECRETE_FORTE" ]; then + echo "❌ SESSION_SECRET doit être changé pour la production !" + exit 1 +fi + +echo "✅ Configuration de sécurité validée" + +# Arrêter les services existants +echo "🛑 Arrêt des services existants..." +docker-compose down 2>/dev/null || true + +# Construire les images +echo "🔨 Construction des images de production..." +docker-compose build --no-cache + +# Vérifier l'espace disque +echo "💾 Vérification de l'espace disque..." +DISK_USAGE=$(df / | awk 'NR==2{print $5}' | cut -d'%' -f1) +if [ "$DISK_USAGE" -gt 80 ]; then + echo "⚠️ Attention: Espace disque faible ($DISK_USAGE%)" + read -p "Continuer ? (y/N): " -r + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Démarrer les services avec configuration production +echo "🚀 Démarrage des services de production..." +docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d + +# Attendre le démarrage +echo "⏳ Attente du démarrage des services..." +sleep 30 + +# Vérifier la santé des services +echo "🏥 Vérification de la santé des services..." +for i in {1..30}; do + if docker-compose ps | grep -q "healthy"; then + echo "✅ Services démarrés avec succès" + break + fi + if [ $i -eq 30 ]; then + echo "❌ Timeout: Les services ne démarrent pas correctement" + echo "📋 Logs des services :" + docker-compose logs --tail=20 + exit 1 + fi + sleep 5 +done + +# Test de connectivité +echo "🔗 Test de connectivité..." +if curl -f http://localhost:5000/health &>/dev/null; then + echo "✅ Application accessible sur http://localhost:5000" +else + echo "❌ Application non accessible" + docker-compose logs regisflow --tail=20 + exit 1 +fi + +# Afficher le statut final +echo "" +echo "🎉 DÉPLOIEMENT PRODUCTION RÉUSSI !" +echo "==================================" +echo "📱 Application RegisFlow : http://localhost:5000" +echo "🗄️ PostgreSQL : localhost:5433" +echo "📊 Statut des services :" +docker-compose ps + +echo "" +echo "📋 Commandes utiles :" +echo " - Logs : docker-compose logs -f" +echo " - Statut : docker-compose ps" +echo " - Arrêt : docker-compose down" +echo " - Sauvegarde : docker-compose exec regisflow-db pg_dump -U regisflow regisflow > backup.sql" +echo "" +echo "⚠️ N'oubliez pas de configurer HTTPS avec un reverse proxy pour la production !" \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..f25c7ce --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,61 @@ +# Configuration Docker Compose spécifique PRODUCTION +# Usage: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d + +version: '3.8' + +services: + regisflow-db: + # Configuration production PostgreSQL + command: postgres -c config_file=/etc/postgresql/postgresql.conf + environment: + # Variables supplémentaires pour production + POSTGRES_SHARED_PRELOAD_LIBRARIES: "pg_stat_statements" + volumes: + # Logs PostgreSQL + - postgres_logs:/var/log/postgresql + # Limites strictes en production + deploy: + resources: + limits: + cpus: '1.0' + memory: 512M + reservations: + cpus: '0.5' + memory: 256M + # Politique de redémarrage agressive + restart: always + + regisflow: + # Configuration production application + environment: + # Mode strict en production + NODE_ENV: production + # Optimisations Node.js + NODE_OPTIONS: "--max-old-space-size=512 --unhandled-rejections=strict" + # Logs structurés + LOG_LEVEL: info + LOG_FORMAT: json + # Limites strictes en production + deploy: + resources: + limits: + cpus: '2.0' + memory: 1G + reservations: + cpus: '1.0' + memory: 512M + # Politique de redémarrage agressive + restart: always + # Configuration ulimits pour production + ulimits: + nofile: + soft: 65536 + hard: 65536 + +volumes: + postgres_logs: + driver: local + driver_opts: + type: none + o: bind + device: ${PWD}/data/postgres-logs \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index e7c3f9b..e4dfc5d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,29 +1,46 @@ version: '3.8' +# Configuration Docker Compose pour PRODUCTION RegisFlow services: - # Base de données PostgreSQL + # Base de données PostgreSQL (Production) regisflow-db: image: postgres:15-alpine container_name: regisflow-db environment: POSTGRES_DB: regisflow POSTGRES_USER: regisflow - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-RegisFlow2024!} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + # Optimisations PostgreSQL pour production + POSTGRES_INITDB_ARGS: "--auth-host=md5 --auth-local=peer" volumes: - postgres_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro + - ./postgres-prod.conf:/etc/postgresql/postgresql.conf:ro ports: - "5433:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"] - interval: 10s - timeout: 5s + interval: 30s + timeout: 10s retries: 5 + start_period: 30s + # Limites de ressources pour production + deploy: + resources: + limits: + memory: 512M + reservations: + memory: 256M + # Configuration réseau sécurisée + networks: + - regisflow-internal - # Application RegisFlow + # Application RegisFlow (Production) regisflow: - build: . + build: + context: . + target: production container_name: regisflow-app depends_on: regisflow-db: @@ -31,23 +48,70 @@ services: environment: NODE_ENV: production PORT: 5000 - DATABASE_URL: postgresql://regisflow:${POSTGRES_PASSWORD:-RegisFlow2024!}@regisflow-db:5432/regisflow - SESSION_SECRET: ${SESSION_SECRET:-your-super-secret-session-key-change-in-production} - TZ: Europe/Paris + DATABASE_URL: postgresql://regisflow:${POSTGRES_PASSWORD}@regisflow-db:5432/regisflow + SESSION_SECRET: ${SESSION_SECRET} + TZ: ${TZ:-Europe/Paris} + # Configuration sécurité production + 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} volumes: - backup_data:/app/backups + - logs_data:/app/logs ports: - "5000:5000" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"] interval: 30s - timeout: 10s + timeout: 15s retries: 3 - start_period: 60s + start_period: 90s + # Limites de ressources pour production + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 512M + # Configuration réseau sécurisée + networks: + - regisflow-internal + # Sécurité container + security_opt: + - no-new-privileges:true + read_only: false + tmpfs: + - /tmp +# Volumes persistants pour production volumes: postgres_data: driver: local + driver_opts: + type: none + o: bind + device: ${PWD}/data/postgres backup_data: - driver: local \ No newline at end of file + driver: local + driver_opts: + type: none + o: bind + device: ${PWD}/data/backups + logs_data: + driver: local + driver_opts: + type: none + o: bind + device: ${PWD}/data/logs + +# Réseau interne sécurisé +networks: + regisflow-internal: + driver: bridge + internal: false + ipam: + driver: default + config: + - subnet: 172.20.0.0/24 \ No newline at end of file diff --git a/monitoring.sh b/monitoring.sh new file mode 100755 index 0000000..5007be6 --- /dev/null +++ b/monitoring.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +# Script de monitoring pour RegisFlow Production +# Usage: ./monitoring.sh [check|logs|backup|stats] + +COMMAND=${1:-check} + +case $COMMAND in + "check") + echo "🔍 Vérification de l'état des services RegisFlow" + echo "==============================================" + + echo "📊 Statut des containers :" + docker-compose ps + + echo "" + echo "🏥 Health checks :" + + # Vérifier RegisFlow + if curl -f -s http://localhost:5000/health > /dev/null; then + echo "✅ RegisFlow : OK" + else + echo "❌ RegisFlow : ERREUR" + fi + + # Vérifier PostgreSQL + if docker-compose exec -T regisflow-db pg_isready -U regisflow -q; then + echo "✅ PostgreSQL : OK" + else + echo "❌ PostgreSQL : ERREUR" + fi + + echo "" + echo "💾 Utilisation des ressources :" + docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" + + echo "" + echo "💿 Espace disque :" + df -h | grep -E "(Filesystem|/dev/)" + + echo "" + echo "📁 Taille des volumes :" + du -sh data/* 2>/dev/null || echo "Répertoire data non trouvé" + ;; + + "logs") + echo "📋 Logs des services RegisFlow" + echo "==============================" + + echo "📱 Logs RegisFlow (20 dernières lignes) :" + docker-compose logs --tail=20 regisflow + + echo "" + echo "🗄️ Logs PostgreSQL (20 dernières lignes) :" + docker-compose logs --tail=20 regisflow-db + ;; + + "backup") + echo "💾 Création d'une sauvegarde manuelle" + echo "====================================" + + BACKUP_FILE="backup-$(date +%Y%m%d-%H%M%S).sql" + + echo "Création de la sauvegarde : $BACKUP_FILE" + docker-compose exec -T regisflow-db pg_dump -U regisflow regisflow > "data/backups/$BACKUP_FILE" + + if [ $? -eq 0 ]; then + echo "✅ Sauvegarde créée avec succès : data/backups/$BACKUP_FILE" + echo "📊 Taille : $(ls -lh data/backups/$BACKUP_FILE | awk '{print $5}')" + else + echo "❌ Erreur lors de la création de la sauvegarde" + fi + ;; + + "stats") + echo "📊 Statistiques détaillées RegisFlow" + echo "====================================" + + echo "🔢 Statistiques base de données :" + docker-compose exec -T regisflow-db psql -U regisflow -d regisflow -c " + SELECT + schemaname, + tablename, + pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size, + pg_stat_get_tuples_returned(c.oid) as tuple_read, + pg_stat_get_tuples_fetched(c.oid) as tuple_fetch, + pg_stat_get_tuples_inserted(c.oid) as tuple_insert, + pg_stat_get_tuples_updated(c.oid) as tuple_update, + pg_stat_get_tuples_deleted(c.oid) as tuple_delete + FROM pg_tables t + LEFT JOIN pg_class c ON c.relname = t.tablename + WHERE schemaname = 'public' + ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC; + " + + echo "" + echo "📁 Utilisation des volumes Docker :" + docker system df + + echo "" + echo "🔄 Uptime des services :" + docker-compose ps --format "table {{.Name}}\t{{.Status}}" + + echo "" + echo "📈 Métriques système :" + echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%" + echo "RAM: $(free -m | awk 'NR==2{printf "%.1f%%", $3*100/$2 }')" + echo "Disk: $(df / | awk 'NR==2{print $5}')" + ;; + + *) + echo "Usage: $0 [check|logs|backup|stats]" + echo "" + echo "Commandes disponibles :" + echo " check - Vérifier l'état des services" + echo " logs - Afficher les logs" + echo " backup - Créer une sauvegarde manuelle" + echo " stats - Afficher les statistiques détaillées" + ;; +esac \ No newline at end of file diff --git a/nginx-reverse-proxy.conf b/nginx-reverse-proxy.conf new file mode 100644 index 0000000..85ee168 --- /dev/null +++ b/nginx-reverse-proxy.conf @@ -0,0 +1,84 @@ +# Configuration Nginx pour RegisFlow Production +# Placez ce fichier dans /etc/nginx/sites-available/regisflow +# Puis créez un lien : ln -s /etc/nginx/sites-available/regisflow /etc/nginx/sites-enabled/ + +server { + listen 80; + server_name votre-domaine.com www.votre-domaine.com; + + # Redirection automatique vers HTTPS + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name votre-domaine.com www.votre-domaine.com; + + # Configuration 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 sécurisée + 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; + + # Sécurité headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options DENY always; + add_header X-Content-Type-Options nosniff always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always; + + # Configuration des logs + access_log /var/log/nginx/regisflow_access.log; + error_log /var/log/nginx/regisflow_error.log; + + # Limite de taille des uploads + client_max_body_size 10M; + + # Configuration du proxy vers RegisFlow + location / { + proxy_pass http://127.0.0.1:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + 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_cache_bypass $http_upgrade; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + # Optimisations pour les fichiers statiques + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + proxy_pass http://127.0.0.1:5000; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Health check + location /health { + proxy_pass http://127.0.0.1:5000/health; + access_log off; + } + + # Protection contre les attaques + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # Limitation du taux de requêtes + limit_req_zone $binary_remote_addr zone=regisflow:10m rate=10r/s; + limit_req zone=regisflow burst=20 nodelay; +} \ No newline at end of file diff --git a/postgres-prod.conf b/postgres-prod.conf new file mode 100644 index 0000000..6a6d3a0 --- /dev/null +++ b/postgres-prod.conf @@ -0,0 +1,45 @@ +# Configuration PostgreSQL optimisée pour production RegisFlow + +# Connexions et authentification +max_connections = 50 +shared_buffers = 128MB +effective_cache_size = 256MB +work_mem = 4MB +maintenance_work_mem = 32MB + +# WAL et checkpoint +wal_buffers = 4MB +checkpoint_completion_target = 0.9 +max_wal_size = 256MB +min_wal_size = 80MB + +# Logging pour production +log_destination = 'stderr' +logging_collector = on +log_directory = '/var/log/postgresql' +log_filename = 'postgresql-%Y-%m-%d.log' +log_statement = 'mod' +log_min_duration_statement = 1000 +log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' + +# Sécurité +ssl = off +password_encryption = md5 +shared_preload_libraries = '' + +# Performance +random_page_cost = 1.1 +effective_io_concurrency = 200 +default_statistics_target = 100 + +# Timeouts +statement_timeout = 30000 +lock_timeout = 5000 +idle_in_transaction_session_timeout = 300000 + +# Autovacuum optimisé pour RegisFlow +autovacuum = on +autovacuum_max_workers = 2 +autovacuum_naptime = 30s +autovacuum_vacuum_threshold = 50 +autovacuum_analyze_threshold = 50 \ No newline at end of file diff --git a/replit.md b/replit.md index d9354ed..5b0ce9f 100644 --- a/replit.md +++ b/replit.md @@ -212,4 +212,15 @@ Preferred communication style: Simple, everyday language. - ✅ Environment variable configuration with preconfigured PostgreSQL credentials - ✅ Comprehensive Docker documentation with deployment instructions - ✅ Nginx configuration removed for simplified deployment (application accessible on port 5000) -- ✅ Preconfigured PostgreSQL user (regisflow/RegisFlow2024!) - only IP change needed \ No newline at end of file +- ✅ Preconfigured PostgreSQL user (regisflow/RegisFlow2024!) - only IP change needed + +### Production Deployment System (January 9, 2025) +- ✅ Multi-stage Dockerfile optimized for production with security hardening +- ✅ Production-specific Docker Compose configuration with resource limits +- ✅ PostgreSQL production configuration with performance optimizations +- ✅ Automated production deployment script with security validations +- ✅ Nginx reverse proxy configuration with SSL/TLS and security headers +- ✅ Comprehensive monitoring script for health checks, logs, and statistics +- ✅ Enhanced environment configuration with mandatory security variables +- ✅ Production-ready logging, backup retention, and data persistence +- ✅ Container security hardening with non-root user and resource limits \ No newline at end of file