Configuration
The gateway has no IGNIS env-var surface and no
Configurationtable. Its configuration is three files plus the portal's build-time constants.
1. Traefik Static Config
Source: packages/gateway/config/traefik.yml
| Section | Value | Notes |
|---|---|---|
api.dashboard | true | Dashboard enabled (auth via file-provider router, not api.insecure) |
entryPoints.web | :80 | HTTP entrypoint — receives traffic from edge Nginx |
entryPoints.traefik | :8080 | Dashboard + Prometheus metrics |
| HTTPS entrypoint | absent | TLS terminated at edge Nginx, not Traefik |
providers.docker | unix:///var/run/docker.sock, exposedByDefault: false, network: nx-network | Routers self-register via labels |
providers.file | directory: /etc/traefik/dynamic, watch: true | Hot-reloads middlewares.yml |
log | level: INFO, format: json | App/startup logs |
accessLog | format: json, drops Authorization + Cookie | Per-request logs |
metrics.prometheus | entryPoint: traefik, entrypoint/router/service labels on | Scraped on :8080 |
2. Traefik Dynamic Config (Middlewares)
Source: packages/gateway/config/dynamic/middlewares.yml
Defines the dashboard routers and the shared middleware set referenced by service Docker labels with the @file suffix. Full breakdown: see Middlewares.
| Middleware | Summary |
|---|---|
circuit-breaker | NetworkErrorRatio() > 0.10 || LatencyAtQuantileMS(95.0) > 3000 (5xx-ratio term commented out) |
rate-limit | 200/s, burst 400, ipStrategy.depth=1 |
rate-limit-auth | 30/min, burst 60, ipStrategy.depth=1 |
security-headers | XSS filter, nosniff, frame deny, strip Server/X-Powered-By |
dashboard-auth | basic auth (nx.eventry:…) for the Traefik dashboard + portal |
redirect-to-dashboard | ^/$ → /dashboard/ on the traefik entrypoint |
3. Local Nginx Route Table (Native Dev)
Source: packages/gateway/local/nginx.conf + local/docker-compose.yml
Container local-nx-gateway (nginx:1.27-alpine) runs with host networking (Linux-only) so it binds :80 and reaches native services on 127.0.0.1:31xx. Paths are forwarded verbatim — no rewriting — because each service mounts at its own APP_ENV_SERVER_BASE_PATH.
Upstreams
| Service | Upstream | Port |
|---|---|---|
| identity | identity_upstream | 127.0.0.1:31010 |
| commerce | commerce_upstream | 127.0.0.1:31020 |
| sale | sale_upstream | 127.0.0.1:31030 |
| finance | finance_upstream | 127.0.0.1:31040 |
| inventory | inventory_upstream | 127.0.0.1:31050 |
| ledger | ledger_upstream | 127.0.0.1:31060 |
| pricing | pricing_upstream | 127.0.0.1:31070 |
| payment | payment_upstream | 127.0.0.1:31080 |
| signal | signal_upstream | 127.0.0.1:31090 |
| outreach | outreach_upstream | 127.0.0.1:31110 |
| licensing | licensing_upstream | 127.0.0.1:31120 |
| taxation | taxation_upstream | 127.0.0.1:31130 |
| invoice | invoice_upstream | 127.0.0.1:31140 |
Locations
| Location | Target | Notes |
|---|---|---|
/v1/api/<svc>/ (13 above) | matching upstream | HTTP REST, verbatim forward |
= /stream | signal_upstream | Signal WebSocket; Upgrade/Connection headers, 3600s timeouts |
= /__gateway_health | — | Returns 200 {"status":"ok","gateway":"local-nx-gateway"} |
/ | — | Unmatched → 404 {"error":"not found",...} (fail fast) |
Shared
proxy_*settings:proxy_http_version 1.1, forwardsHost/X-Real-IP/X-Forwarded-*,client_max_body_size 50m, 300s read/send timeouts. The FE uses a single base URL (http://sgw.local.bana.com.vn/v1/api).
4. Portal Configuration
Source: packages/gateway/portal/astro.config.ts, portal/package.json
| Setting | Value |
|---|---|
| Output | static |
| Dev server | port 3003, host: true |
| Preview | port 4173 |
| Container port | 8080 (served by nginxinc/nginx-unprivileged:1.27-alpine) |
| Chunk warn limit | 400 kB |
The portal has no build-time dependency on backend packages. It discovers services at runtime: it derives the base domain from window.location.hostname (e.g. sgw.develop.bana.com.vn → develop.bana.com.vn; SSR fallback develop.bana.com.vn) and fetches each service's /health and /doc/openapi.json.
5. Service & App Constant Lists
The portal's catalog is hand-maintained as TypeScript constants — the single source the portal renders from.
Services — portal/src/constants/services.constant.ts
14 entries (Services.ITEMS), each { id, name, pkg, icon, basePath, desc }:
| id | pkg | basePath |
|---|---|---|
| identity | @nx/identity | /v1/api/identity |
| commerce | @nx/commerce | /v1/api/commerce |
| sale | @nx/sale | /v1/api/sale |
| finance | @nx/finance | /v1/api/finance |
| inventory | @nx/inventory | /v1/api/inventory |
| payment | @nx/payment | /v1/api/payment |
| pricing | @nx/pricing | /v1/api/pricing |
| taxation | @nx/taxation | /v1/api/taxation |
| signal | @nx/signal | /v1/api/signal |
| ledger | @nx/ledger | /v1/api/ledger |
| invoice | @nx/invoice | /v1/api/invoice |
| outreach | @nx/outreach | /v1/api/outreach |
| licensing | @nx/licensing | /v1/api/licensing |
| helpdesk | @nx/helpdesk | /v1/api/helpdesk |
Drift note: the portal lists 14 services (includes
helpdesk); the local Nginx route table lists 13 (nohelpdesk). AGENTS.md states "13 services" — the source has since addedhelpdesk. Reconcile whenhelpdeskships a route.
Apps — portal/src/constants/apps.constant.ts
4 frontend apps (Apps.ITEMS), URL derived per-environment from the subdomain:
| id | name | subdomain |
|---|---|---|
| client | Client (admin dashboard) | client |
| bo | BO (back office) | bo |
| sale | Sale | sale |
| wiki | Wiki / Docs (VitePress) | docs |
6. Feature Flags / Seeded Data / Configuration Storage
N/A — the gateway has no feature-flag system, no seed migrations, and no Configuration table (no datastore).