rubis/apps/web/nginx.conf
ordinarthur dd93249362
All checks were successful
Build & Deploy Web / build-and-deploy (push) Successful in 1m16s
Build & Deploy API / build-and-deploy (push) Successful in 1m32s
refactor(deploy): split monolithique en 2 services (rubis-web nginx + rubis-api Node)
Avant : une seule image (Dockerfile.app) qui bundle AdonisJS + SPA static.
Après : deux images, deux deployments, deux workflows CI avec path filters
indépendants.

Architecture
- rubis-web (NodePort 30110, exposé via Traefik)
  · nginx-alpine + SPA Vite dist + nginx.conf
  · sert /assets/* (cache 1y immutable), / (try_files index.html SPA fallback)
  · reverse-proxy /api/* → rubis-api.rubis.svc.cluster.local:3333
- rubis-api (ClusterIP, accessible uniquement depuis le cluster)
  · AdonisJS V7 + workers BullMQ dans le même process
  · init-container migrate (idempotent, depuis build/)
  · /api/v1/health pour les probes K3s + healthcheck Docker
- rubis-redis (ClusterIP, inchangé)

Bénéfices
- Build/deploy indépendants : changement front ne reconstruit pas l'API,
  changement API ne reconstruit pas le SPA
- nginx en frontal donne du gzip + cache long sur les assets fingerprintés
- API n'expose plus de surface publique (defense in depth)
- Routes plus simples : on retire le wildcard SPA fallback dans
  start/routes.ts (nginx s'en charge), on retire @adonisjs/static aurait
  été cohérent mais on le garde pour minimiser les diffs

Files
- Dockerfile.api (replaces Dockerfile.app, Node-only)
- Dockerfile.web (new, nginx)
- apps/web/nginx.conf (new)
- k3s/app/api.yml (replaces deployment.yml + service.yml, ClusterIP)
- k3s/app/web.yml (new, NodePort 30110)
- .gitea/workflows/deploy-{api,web}.yml (replaces deploy-app.yml)
- /api/v1/health route ajoutée

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 02:58:25 +02:00

75 lines
2.2 KiB
Nginx Configuration File

# nginx.conf — reverse proxy + SPA static pour rubis-web
#
# Sert :
# - / → assets SPA + index.html avec fallback try_files (TanStack Router)
# - /api/* → reverse proxy vers le service ClusterIP rubis-api:3333
#
# Le service rubis-api est interne au cluster K3s (pas de NodePort).
# Seul nginx (NodePort 30110 → Traefik) est exposé.
upstream rubis_api {
server rubis-api.rubis.svc.cluster.local:3333 max_fails=3 fail_timeout=10s;
keepalive 32;
}
# Compression gzip — Vite produit déjà du JS minifié, mais HTML/CSS/SVG
# bénéficient toujours du gzip on-the-fly.
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types
application/javascript
application/json
application/xml
text/css
text/html
text/plain
image/svg+xml;
server {
listen 80 default_server;
server_name _;
root /var/www;
index index.html;
# Limite raisonnable pour les uploads de factures (PDF, photos).
client_max_body_size 25m;
# Désactive les logs sur les ressources qui spamment (favicon, robots).
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; }
# Assets fingerprintés Vite : cache long, immutable.
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
# API → reverse proxy vers AdonisJS (rubis-api ClusterIP).
# Inclut /api/v1/checkin/* qui sert les liens reçus par email.
location /api/ {
proxy_pass http://rubis_api;
proxy_http_version 1.1;
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 https;
proxy_set_header Connection "";
# Timeouts adaptés au plus long endpoint (upload OCR Mistral).
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# SPA fallback : toute route non-asset, non-API → index.html
# (TanStack Router gère côté client).
location / {
try_files $uri $uri/ /index.html;
# index.html lui-même : pas de cache (pour récupérer les nouveaux
# builds sans purger côté client).
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}