rubis/apps/web/nginx.conf
ordinarthur 3fc3a7456a
Some checks failed
Build & Deploy Web / build-and-deploy (push) Has been cancelled
Build & Deploy API / build-and-deploy (push) Successful in 2m30s
Build & Deploy Landing / build-and-deploy (push) Successful in 1m31s
feat(web): instrumentation PostHog (analytics + nginx proxy)
Setup PostHog côté SPA — pageviews TanStack Router + 10 events business
(signup, login SSO, upload facture, émission/brouillon facture native,
marquer payée, lancer relance, plan créé, checkout Stripe). PostHogProvider
dans __root.tsx, identify sur auth, proxy nginx /ingest/* → eu.i.posthog.com
pour contourner les adblockers. Token bake via build-arg CI
(POSTHOG_PROJECT_TOKEN, à ajouter côté Gitea Secrets).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 17:21:59 +02:00

116 lines
3.7 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
# - /ingest/* → reverse proxy vers PostHog EU (contourne les adblockers)
#
# 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;
}
# PostHog ingestion endpoint (EU) — proxifié pour passer les adblockers
# qui bloquent *.posthog.com directement. Le SDK est configuré avec
# api_host: "/ingest" (cf. src/routes/__root.tsx).
upstream posthog_ingest {
server eu.i.posthog.com:443;
keepalive 8;
}
# Assets PostHog (static.js, array.js, recorder) — domaine distinct chez PostHog.
upstream posthog_assets {
server eu-assets.i.posthog.com:443;
keepalive 8;
}
# 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;
}
# PostHog assets (loader JS) — /ingest/static/* et /ingest/array/* vont
# vers eu-assets.i.posthog.com (CDN). Doit être déclaré AVANT /ingest/
# car nginx matche par prefix le plus long.
location ~ ^/ingest/(static|array)/ {
rewrite ^/ingest/(.*)$ /$1 break;
proxy_pass https://posthog_assets;
proxy_http_version 1.1;
proxy_set_header Host eu-assets.i.posthog.com;
proxy_set_header Connection "";
proxy_ssl_server_name on;
proxy_ssl_name eu-assets.i.posthog.com;
}
# PostHog ingestion (events, sessions, exceptions) — /ingest/* → eu.i.posthog.com
location /ingest/ {
rewrite ^/ingest/(.*)$ /$1 break;
proxy_pass https://posthog_ingest;
proxy_http_version 1.1;
proxy_set_header Host eu.i.posthog.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Connection "";
proxy_ssl_server_name on;
proxy_ssl_name eu.i.posthog.com;
proxy_redirect off;
}
# 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";
}
}