# Rubis App — apps/api (AdonisJS) + apps/web (React) bundlés dans une image # unique. Le SPA est servi par le static middleware AdonisJS, le wildcard # fallback gère le routing TanStack Router. Workers BullMQ tournent dans le # même process (cf. start/queue.ts). --- apiVersion: apps/v1 kind: Deployment metadata: name: rubis-app namespace: rubis spec: replicas: 1 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: rubis-app template: metadata: labels: app: rubis-app spec: imagePullSecrets: - name: gitea-registry # Migrations exécutées en init-container avant que le serveur démarre. # Idempotent (ace migration:run skip ce qui est déjà appliqué). initContainers: - name: migrate image: git.arthurbarre.fr/ordinarthur/rubis-app:latest # On exécute ace depuis build/ (compilé JS) — le shim ace.js de # /app/apps/api/ charge bin/console.ts (TS) qui n'a pas de loader # disponible en runtime sans devDeps. workingDir: /app/apps/api/build command: ['node', 'ace.js', 'migration:run', '--force'] envFrom: - secretRef: { name: rubis-app-secrets } - configMapRef: { name: rubis-app-config } resources: requests: { cpu: 50m, memory: 128Mi } limits: { cpu: 500m, memory: 512Mi } containers: - name: app image: git.arthurbarre.fr/ordinarthur/rubis-app:latest imagePullPolicy: Always ports: - containerPort: 3333 name: http envFrom: - secretRef: { name: rubis-app-secrets } - configMapRef: { name: rubis-app-config } resources: requests: cpu: 100m memory: 256Mi limits: cpu: 1000m memory: 768Mi # Probes adaptées au boot AdonisJS (peut prendre 10-15s avec BullMQ) startupProbe: httpGet: { path: /, port: http } initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 30 # 150s max livenessProbe: httpGet: { path: /, port: http } periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: { path: /, port: http } periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 --- apiVersion: v1 kind: ConfigMap metadata: name: rubis-app-config namespace: rubis data: # Variables non-sensibles. Les secrets sont dans rubis-app-secrets. TZ: 'Europe/Paris' PORT: '3333' HOST: '0.0.0.0' NODE_ENV: 'production' LOG_LEVEL: 'info' APP_URL: 'https://app.rubis.arthurbarre.fr' WEB_URL: 'https://app.rubis.arthurbarre.fr' SESSION_DRIVER: 'cookie' COOKIE_SECURE: 'true' COOKIE_DOMAIN: 'app.rubis.arthurbarre.fr' DB_CONNECTION: 'postgres' PG_HOST: '10.10.10.3' PG_PORT: '5432' PG_USER: 'rubis' PG_DB_NAME: 'rubis_prod' REDIS_HOST: 'rubis-redis.rubis.svc.cluster.local' REDIS_PORT: '6379' LIMITER_STORE: 'redis' # MinIO interne (pas via le NodePort public, plus rapide + plus sécurisé). DRIVE_DISK: 's3' S3_ENDPOINT: 'http://minio.minio.svc.cluster.local:9000' S3_REGION: 'fr-par' S3_BUCKET: 'rubis-prod-invoices' S3_FORCE_PATH_STYLE: 'true' MAIL_DRIVER: 'resend' MAIL_FROM_ADDRESS: 'rubis@arthurbarre.fr' MAIL_FROM_NAME: "Rubis Sur l'Ongle" OCR_PROVIDER: 'mistral' ACCESS_TOKEN_TTL_MINUTES: '30' REFRESH_TOKEN_TTL_DAYS: '30'