From 318b83625a0bf4331a2fecc4d48c8222b93cd49e Mon Sep 17 00:00:00 2001 From: LincPay Date: Sat, 15 Aug 2026 15:33:21 +0530 Subject: [PATCH] build(deploy): relative API base and a same-origin /api proxy --- Dockerfile | 10 ++++++++-- nginx.conf | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9ab25f7..668baf5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,14 @@ WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . -# VITE_UDYAM_API_BASE_URL is unset here, so the compiled-in default -# (http://udyamlinc-backend.lincpay/api/v1/udyam) is baked into the bundle. +# Vite inlines this at build time, so it is a build arg and not a runtime env +# var — changing it later means rebuilding the bundle, not restarting nginx. +# +# Relative on purpose. A bundle carrying no hostname serves from any domain and +# is same-origin with the API that nginx proxies at /api/, so the deployment +# never has a CORS origin to keep in sync. +ARG VITE_UDYAM_API_BASE_URL=/api/v1/udyam +ENV VITE_UDYAM_API_BASE_URL=$VITE_UDYAM_API_BASE_URL RUN npm run build # ── serve stage: nginx serving the static SPA on 5173 ── diff --git a/nginx.conf b/nginx.conf index d988963..da0ee43 100644 --- a/nginx.conf +++ b/nginx.conf @@ -19,6 +19,30 @@ server { add_header Cache-Control "no-cache, no-store, must-revalidate"; } + # The API, same-origin. The bundle is built with VITE_UDYAM_API_BASE_URL set + # to the relative /api/v1/udyam, so it carries no hostname at all and the + # same dist/ serves from any domain. That also puts the API on the UI's own + # origin, which means CORS never enters the picture — the single largest + # source of "works locally, fails deployed" in a split deployment. + # + # The backend's context-path is already /api/v1/udyam, so the prefix is + # passed through unchanged rather than rewritten. + location /api/ { + proxy_pass http://127.0.0.1:8082; + 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 $scheme; + + # Ingestion and the three-year backfill are long-running admin calls; + # the default 60s read timeout cuts them off mid-run and reports a + # gateway error over a job that is still working. + proxy_connect_timeout 30s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; + } + # SPA fallback — React Router owns the paths location / { try_files $uri $uri/ /index.html;