From 325b1b7c1052c98d8c2247f2a2ac2b5ccffa41a9 Mon Sep 17 00:00:00 2001 From: Xor290 Date: Thu, 22 Jan 2026 22:23:37 +0100 Subject: [PATCH] chore: update nginx docker compose --- ansible/playbook-docker.yml | 2 +- docker/backend/Dockerfile | 5 +- docker/docker-compose-prod.yml | 17 +- docker/docker-compose.yml | 134 --- docker/frontend/Dockerfile | 4 +- docker/frontend/Dockerfile.prod | 49 - docker/frontend/custom-rules.conf | 7 + docker/frontend/nginx.conf | 62 +- .../src/components/ProductDetailsModal.tsx | 6 +- .../src/components/ProductEditModal.tsx | 936 ++++++++++-------- .../src/pages/AdminProduct/AdminProduct.tsx | 2 +- frontend-prep/src/pages/User/Accueil.tsx | 6 +- frontend-prep/src/pages/User/Cart.tsx | 6 +- frontend-prep/src/pages/User/OrderDetails.tsx | 6 +- s2.sh | 2 +- 15 files changed, 606 insertions(+), 638 deletions(-) delete mode 100644 docker/docker-compose.yml delete mode 100644 docker/frontend/Dockerfile.prod diff --git a/ansible/playbook-docker.yml b/ansible/playbook-docker.yml index e47faeb0..562851ea 100644 --- a/ansible/playbook-docker.yml +++ b/ansible/playbook-docker.yml @@ -191,7 +191,7 @@ - name: Set permissions for .env file ansible.builtin.file: - path: "{{ docker_dir }}/docker/.env" + path: "{{ docker_dir }}/.env" owner: "{{ docker_user }}" group: "{{ docker_group }}" mode: "0640" diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index ebd1befe..c3edc50f 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -32,7 +32,8 @@ FROM alpine:latest RUN apk --no-cache add ca-certificates tzdata wget # Créer l'utilisateur avec UID/GID fixes -RUN addgroup -g 1000 app && adduser -u 1000 -S app -G app +RUN addgroup -g 101 app && adduser -u 101 -S app -G app + WORKDIR /app @@ -41,7 +42,7 @@ COPY --from=builder /app/server . COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo # Copier l'entrypoint -COPY docker/docker/backend/entrypoint.sh . +COPY docker/backend/entrypoint.sh . RUN chmod +x entrypoint.sh # ✅ Créer le dossier uploads et donner ownership AVANT de changer d'utilisateur diff --git a/docker/docker-compose-prod.yml b/docker/docker-compose-prod.yml index 039b6093..4926b921 100644 --- a/docker/docker-compose-prod.yml +++ b/docker/docker-compose-prod.yml @@ -4,8 +4,8 @@ services: # ========================================================= backend: build: - context: ../.. - dockerfile: docker/docker/backend/Dockerfile + context: .. + dockerfile: docker/backend/Dockerfile container_name: gestion-backend restart: unless-stopped environment: @@ -26,7 +26,8 @@ services: - TOMTOM_API_KEY=${TOMTOM_API_KEY} - API_PORT=${API_PORT:-8080} volumes: - - backend_uploads:/app/uploads + # ✅ Volume partagé pour les uploads (même volume que le frontend) + - frontend_uploads:/app/uploads networks: - gestion-network depends_on: @@ -40,8 +41,8 @@ services: # ========================================================= frontend: build: - context: ../.. - dockerfile: docker/docker/frontend/Dockerfile + context: .. + dockerfile: docker/frontend/Dockerfile container_name: gestion-frontend restart: unless-stopped environment: @@ -53,6 +54,9 @@ services: - BACKEND_PORT=${API_PORT:-8080} ports: - "80:80" + volumes: + # ✅ Volume partagé pour les uploads (accessible via nginx) + - frontend_uploads:/usr/share/nginx/html/uploads networks: - gestion-network @@ -128,5 +132,6 @@ volumes: driver: local redis_data: driver: local - backend_uploads: + # ✅ Volume partagé entre backend et frontend + frontend_uploads: driver: local diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 50fab889..00000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,134 +0,0 @@ -services: - # ========================================================= - # Backend Go - # ========================================================= - backend: - build: - context: .. - dockerfile: docker/backend/Dockerfile - container_name: gestion-backend - restart: unless-stopped - environment: - - DB_HOST=${DB_HOST:-postgres} - - DB_PORT=${DB_PORT:-5432} - - DB_USER=${DB_USER:-postgres} - - DB_PASSWORD=${DB_PASSWORD} - - DB_NAME=${DB_NAME:-gestion_db} - - DB_SSLMODE=${DB_SSLMODE:-disable} - - SESSION_SECRET=${SESSION_SECRET} - - USER_JWT_SECRET=${USER_JWT_SECRET} - - USER_JWT_SECRET_OLD=${USER_JWT_SECRET_OLD} - - ADMIN_JWT_SECRET=${ADMIN_JWT_SECRET} - - ADMIN_JWT_SECRET_OLD=${ADMIN_JWT_SECRET_OLD} - - REDIS_HOST=${REDIS_HOST:-redis} - - REDIS_PORT=${REDIS_PORT:-6379} - - REDIS_PASSWORD=${REDIS_PASSWORD} - - TOMTOM_API_KEY=${TOMTOM_API_KEY} - - API_PORT=${API_PORT:-8080} - ports: - - "${API_PORT:-8080}:8080" - volumes: - - backend_uploads:/app/uploads - networks: - - gestion-network - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - - # ========================================================= - # Frontend Nginx + ModSecurity - # ========================================================= - frontend: - build: - context: .. - dockerfile: docker/frontend/Dockerfile - container_name: gestion-frontend - restart: unless-stopped - environment: - - MODSEC_RULE_ENGINE=On - - PARANOIA=2 - - ANOMALY_INBOUND=5 - - ANOMALY_OUTBOUND=4 - - BACKEND_PORT=${API_PORT:-8080} - ports: - - "80:80" - networks: - - gestion-network - - # ========================================================= - # PostgreSQL - # ========================================================= - postgres: - image: postgres:16-alpine - container_name: gestion-postgres - restart: unless-stopped - environment: - - POSTGRES_USER=${DB_USER:-postgres} - - POSTGRES_PASSWORD=${DB_PASSWORD} - - POSTGRES_DB=${DB_NAME:-gestion_db} - - PGDATA=/var/lib/postgresql/data/pgdata - volumes: - - postgres_data:/var/lib/postgresql/data - ports: - - "${DB_PORT:-5432}:5432" - networks: - - gestion-network - healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-gestion_db}", - ] - interval: 10s - timeout: 5s - retries: 5 - start_period: 10s - - # ========================================================= - # Redis - # ========================================================= - redis: - image: redis:7-alpine - container_name: gestion-redis - restart: unless-stopped - command: > - redis-server - --requirepass ${REDIS_PASSWORD} - --appendonly yes - --appendfsync everysec - --maxmemory 256mb - --maxmemory-policy allkeys-lru - volumes: - - redis_data:/data - ports: - - "${REDIS_PORT:-6379}:6379" - networks: - - gestion-network - healthcheck: - test: - [ - "CMD", - "redis-cli", - "--no-auth-warning", - "-a", - "${REDIS_PASSWORD}", - "ping", - ] - interval: 10s - timeout: 3s - retries: 5 - start_period: 10s - -networks: - gestion-network: - driver: bridge - -volumes: - postgres_data: - driver: local - redis_data: - driver: local - backend_uploads: - driver: local diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index 3a327568..220ad67c 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -36,8 +36,8 @@ COPY --from=builder /build/dist /usr/share/nginx/html # Logs ModSecurity RUN mkdir -p /var/log/modsec && chown -R nginx:nginx /var/log/modsec -COPY docker/docker/frontend/nginx.conf /etc/nginx/conf.d/app.conf -COPY docker/docker/frontend/custom-rules.conf /etc/nginx/modsec/custom-rules.conf +COPY docker/frontend/nginx.conf /etc/nginx/conf.d/app.conf +COPY docker/frontend/custom-rules.conf /etc/nginx/modsec/custom-rules.conf RUN echo "Include /etc/nginx/modsec/custom-rules.conf" > /etc/nginx/modsec/custom-includes.conf RUN rm -f /etc/nginx/templates/conf.d/default.conf.template || true diff --git a/docker/frontend/Dockerfile.prod b/docker/frontend/Dockerfile.prod deleted file mode 100644 index 7f7548a5..00000000 --- a/docker/frontend/Dockerfile.prod +++ /dev/null @@ -1,49 +0,0 @@ -# ========================================================= -# Stage 1: Build Frontend -# ========================================================= -FROM node:20-alpine AS builder - -WORKDIR /build - -COPY frontend-prep/package*.json ./ -RUN npm ci --only=production - -COPY frontend-prep . -RUN npm run build && ls -la dist/ - -# ========================================================= -# Stage 2: Nginx + ModSecurity -# ========================================================= -FROM owasp/modsecurity-crs:nginx-alpine - -USER root - -# Copier le frontend build -COPY --from=builder /build/dist /usr/share/nginx/html - -# Configs Nginx / ModSecurity -COPY docker/frontend/nginx.conf.prod /etc/nginx/conf.d/app.conf -COPY docker/frontend/main.conf /etc/nginx/modsec/main.conf -COPY docker/frontend/ban-on-crs-scores-delivery-api.conf /etc/nginx/modsec/ban-on-crs-scores-delivery-api.conf -COPY docker/frontend/crs-setup.conf /etc/nginx/modsec/crs-setup.conf - -# Supprimer template par défaut -RUN rm -f /etc/nginx/templates/conf.d/default.conf.template || true - -# Variables ModSecurity -ENV MODSEC_ENGINE=On \ - PARANOIA=2 \ - ANOMALY_INBOUND=5 \ - ANOMALY_OUTBOUND=4 - -# Permissions -RUN chown -R nginx:nginx /usr/share/nginx/html \ - && mkdir -p /etc/letsencrypt \ - && chown -R nginx:nginx /etc/letsencrypt - -USER nginx - -EXPOSE 80 443 - -STOPSIGNAL SIGQUIT -CMD ["nginx", "-g", "daemon off;"] diff --git a/docker/frontend/custom-rules.conf b/docker/frontend/custom-rules.conf index c9ffc63d..ce800c19 100644 --- a/docker/frontend/custom-rules.conf +++ b/docker/frontend/custom-rules.conf @@ -6,6 +6,13 @@ SecRule REQUEST_URI "@streq /api/v2/admin/protected/products" \ ctl:ruleRemoveById=920120,\ ctl:ruleRemoveById=920121" +SecRule REQUEST_URI "@beginsWith /uploads/" \ + "id:1000,\ + phase:1,\ + pass,\ + nolog,\ + ctl:ruleEngine=Off" + SecRule IP:BANNED "@eq 1" \ "id:100000,phase:1,deny,status:403,log,\ msg:'IP is banned'" diff --git a/docker/frontend/nginx.conf b/docker/frontend/nginx.conf index c69860b3..34a3532f 100644 --- a/docker/frontend/nginx.conf +++ b/docker/frontend/nginx.conf @@ -67,12 +67,68 @@ server { add_header Pragma "no-cache" always; add_header Expires "0" always; } + location /uploads/ { + # ✅ IMPORTANT : alias doit se terminer par / ET le chemin aussi + alias /usr/share/nginx/html/uploads/; - location ~* \.(css|js|jpg|jpeg|png|gif|svg|ico|woff2?|ttf|eot)$ { - expires 1y; + # ✅ Désactiver ModSecurity pour les uploads + modsecurity off; + + # Cache headers + expires 30d; add_header Cache-Control "public, immutable"; - access_log off; } + location ^~ /uploads/images/ { + alias /usr/share/nginx/html/uploads/images/; + + # ✅ Désactiver ModSecurity + modsecurity off; + + # ✅ CORS pour images publiques + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always; + + # Cache agressif + expires 30d; + add_header Cache-Control "public, immutable" always; + + # Types MIME + types { + image/jpeg jpg jpeg; + image/png png; + image/gif gif; + image/webp webp; + image/svg+xml svg; + } + default_type image/jpeg; + } + + # ========================================================= + # ✅ UPLOADS VIDEOS (priorité maximale avec ^~) + # ========================================================= + location ^~ /uploads/videos/ { + alias /usr/share/nginx/html/uploads/videos/; + + # ✅ Désactiver ModSecurity + modsecurity off; + + # ✅ CORS pour vidéos publiques + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always; + + # Cache agressif + expires 30d; + add_header Cache-Control "public, immutable" always; + + # Types MIME pour vidéos + types { + video/mp4 mp4; + video/webm webm; + video/ogg ogv; + } + default_type video/mp4; + } + add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; diff --git a/frontend-prep/src/components/ProductDetailsModal.tsx b/frontend-prep/src/components/ProductDetailsModal.tsx index 99b8ac3e..202fcae0 100644 --- a/frontend-prep/src/components/ProductDetailsModal.tsx +++ b/frontend-prep/src/components/ProductDetailsModal.tsx @@ -114,14 +114,14 @@ const ProductDetailsModal: React.FC = ({
{currentMedia?.type === "image" ? ( {product.name} ) : currentMedia?.type === "video" ? (