feat: Version 3.5.2 - Configuration Stripe et gestion des immeubles
- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD) * DEV: Clés TEST Pierre (mode test) * REC: Clés TEST Client (mode test) * PROD: Clés LIVE Client (mode live) - Ajout de la gestion des bases de données immeubles/bâtiments * Configuration buildings_database pour DEV/REC/PROD * Service BuildingService pour enrichissement des adresses - Optimisations pages et améliorations ergonomie - Mises à jour des dépendances Composer - Nettoyage des fichiers obsolètes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
290
api/config/nginx/pra-geo-production.conf
Normal file
290
api/config/nginx/pra-geo-production.conf
Normal file
@@ -0,0 +1,290 @@
|
||||
# =============================================================================
|
||||
# Configuration NGINX PRODUCTION pour pra-geo (IN4)
|
||||
# Date: 2025-10-07
|
||||
# Environnement: PRODUCTION
|
||||
# Server: IN4 (51.159.7.190)
|
||||
# =============================================================================
|
||||
|
||||
# Site principal (redirection vers www ou app)
|
||||
server {
|
||||
listen 80;
|
||||
server_name geosector.fr;
|
||||
|
||||
# Redirection permanente vers HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name geosector.fr;
|
||||
|
||||
# Certificats SSL
|
||||
ssl_certificate /etc/letsencrypt/live/geosector.fr/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/geosector.fr/privkey.pem;
|
||||
|
||||
# Configuration SSL optimisée
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
root /var/www/geosector/web;
|
||||
index index.html;
|
||||
|
||||
# Logs PRODUCTION
|
||||
access_log /var/log/nginx/geosector-web_access.log combined;
|
||||
error_log /var/log/nginx/geosector-web_error.log warn;
|
||||
|
||||
# Headers de sécurité
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" 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;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Assets statiques avec cache agressif
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Protection des fichiers sensibles
|
||||
location ~ /\.(?!well-known) {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# APPLICATION FLUTTER + API PHP
|
||||
# =============================================================================
|
||||
|
||||
# Redirection HTTP → HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name app3.geosector.fr;
|
||||
|
||||
# Permettre Let's Encrypt validation
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/letsencrypt;
|
||||
allow all;
|
||||
}
|
||||
|
||||
# Redirection permanente vers HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name app3.geosector.fr;
|
||||
|
||||
# Certificats SSL
|
||||
ssl_certificate /etc/letsencrypt/live/app3.geosector.fr/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/app3.geosector.fr/privkey.pem;
|
||||
|
||||
# Configuration SSL optimisée (même que ci-dessus)
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# Logs PRODUCTION
|
||||
access_log /var/log/nginx/pra-app_access.log combined;
|
||||
error_log /var/log/nginx/pra-app_error.log warn;
|
||||
|
||||
# Headers de sécurité globaux
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" 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;
|
||||
|
||||
# Taille maximale des uploads (pour les logos, exports, etc.)
|
||||
client_max_body_size 10M;
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
# Timeouts optimisés pour PRODUCTION
|
||||
client_body_timeout 30s;
|
||||
client_header_timeout 30s;
|
||||
send_timeout 60s;
|
||||
|
||||
# =============================================================================
|
||||
# APPLICATION FLUTTER (contenu statique)
|
||||
# =============================================================================
|
||||
location / {
|
||||
root /var/www/geosector/app;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Cache intelligent pour PRODUCTION
|
||||
# HTML : pas de cache (pour déploiements)
|
||||
location ~* \.html$ {
|
||||
expires -1;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
|
||||
# Assets Flutter (JS, CSS, fonts) avec hash : cache agressif
|
||||
location ~* \.(js|css|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Images : cache longue durée
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public";
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# API PHP (RESTful)
|
||||
# =============================================================================
|
||||
location /api/ {
|
||||
root /var/www/geosector;
|
||||
|
||||
# CORS - Liste blanche des origines autorisées en PRODUCTION
|
||||
set $cors_origin "";
|
||||
|
||||
# Autoriser uniquement les domaines de production
|
||||
if ($http_origin ~* ^https://(app\.geosector\.fr|geosector\.fr)$) {
|
||||
set $cors_origin $http_origin;
|
||||
}
|
||||
|
||||
# Gestion des preflight requests (OPTIONS)
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' $cors_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
add_header 'Access-Control-Max-Age' 86400;
|
||||
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
# Headers CORS pour les requêtes normales
|
||||
add_header 'Access-Control-Allow-Origin' $cors_origin always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
|
||||
# Cache API : pas de cache (données dynamiques)
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate" always;
|
||||
add_header Pragma "no-cache" always;
|
||||
add_header Expires "0" always;
|
||||
|
||||
# Headers de sécurité spécifiques API
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
|
||||
# Rewrite vers index.php
|
||||
try_files $uri $uri/ /api/index.php$is_args$args;
|
||||
|
||||
# Traitement PHP
|
||||
location ~ ^/api/(.+\.php)$ {
|
||||
root /var/www/geosector;
|
||||
|
||||
# FastCGI PHP-FPM
|
||||
fastcgi_pass unix:/run/php-fpm83/php-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
|
||||
# Variable d'environnement PRODUCTION
|
||||
fastcgi_param APP_ENV "production";
|
||||
fastcgi_param SERVER_NAME "app3.geosector.fr";
|
||||
|
||||
# Headers transmis à PHP
|
||||
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
|
||||
|
||||
# Timeouts pour opérations longues (sync, exports)
|
||||
fastcgi_read_timeout 300;
|
||||
fastcgi_send_timeout 300;
|
||||
fastcgi_connect_timeout 60;
|
||||
|
||||
# Buffers optimisés
|
||||
fastcgi_buffer_size 128k;
|
||||
fastcgi_buffers 256 16k;
|
||||
fastcgi_busy_buffers_size 256k;
|
||||
fastcgi_temp_file_write_size 256k;
|
||||
|
||||
# Headers CORS pour réponses PHP
|
||||
add_header 'Access-Control-Allow-Origin' $cors_origin always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# UPLOADS ET MÉDIAS
|
||||
# =============================================================================
|
||||
location /api/uploads/ {
|
||||
alias /var/www/geosector/api/uploads/;
|
||||
|
||||
# Cache pour les médias uploadés
|
||||
expires 7d;
|
||||
add_header Cache-Control "public";
|
||||
|
||||
# Sécurité : empêcher l'exécution de scripts
|
||||
location ~ \.(php|phtml|php3|php4|php5|phps)$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# SÉCURITÉ
|
||||
# =============================================================================
|
||||
|
||||
# Bloquer l'accès aux fichiers sensibles
|
||||
location ~ /\.(?!well-known) {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Bloquer l'accès aux fichiers de configuration
|
||||
location ~* \.(env|sql|bak|backup|swp|config|conf|ini|log)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Bloquer les user-agents malveillants
|
||||
if ($http_user_agent ~* (bot|crawler|spider|scraper|wget|curl)) {
|
||||
return 403;
|
||||
}
|
||||
|
||||
# Protection contre les requêtes invalides
|
||||
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|PATCH|OPTIONS)$) {
|
||||
return 405;
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MONITORING
|
||||
# =============================================================================
|
||||
|
||||
# Endpoint de health check (accessible uniquement en local)
|
||||
location = /nginx-health {
|
||||
access_log off;
|
||||
allow 127.0.0.1;
|
||||
allow 13.23.34.0/24; # Réseau interne Incus
|
||||
deny all;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user