Proposed
2026-05-22
UMS currently uses nginx embedded inside the ums.web-app Docker image as both a static file server and a reverse proxy to the backend API. This approach is cohesive and sufficient for a single web client.
The planned SaaS evolution introduces at minimum two distinct client surfaces:
ums.web-app — browser SPA (React + Vite)ums.mobile-app — native mobile application (future)With multiple clients, the embedded nginx reverse proxy becomes a liability:
UMS already has Yarp.ReverseProxy as a declared dependency in Ums.Presentation, and the existing IAuthenticationPort abstraction is gateway-compatible. The technology is already present in the stack.
Introduce ums.gateway as a dedicated ASP.NET Core application using YARP as the centralized API Gateway for all UMS clients.
The gateway will be the single entry point for all inbound traffic. nginx will be reduced to a pure static file server with no proxy responsibility.
| Concern | Current Owner | Target Owner |
|---|---|---|
| Static file serving (SPA) | nginx | nginx (unchanged) |
| Reverse proxy to API | nginx (per client) | YARP gateway (centralized) |
| Security headers | nginx.conf | YARP middleware |
| Rate limiting | Not implemented | YARP + IPartitionedRateLimiter |
| Tenant routing | Not implemented | YARP gateway |
| Mobile API access | Direct to API | YARP gateway |
| Auth token validation | API layer | YARP gateway (pre-routing) |
Internet
│
▼
┌──────────────────────────────┐
│ ums.gateway (YARP) │ port 443 / 80
│ ASP.NET Core │ Security headers, Rate limit,
│ │ Tenant routing, Auth check
└────────────┬─────────────────┘
│
┌────────┴──────────┐
▼ ▼
┌──────────┐ ┌──────────────┐
│ ums.api │ │ ums.web-app │ nginx: static only
│ :8080 │ │ :80 │ no proxy logic
└──────────┘ └──────────────┘
▲
ums.mobile-app
(future client,
routes via gateway)
server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
}
All security headers, CSP policies, and proxy configuration migrate to the YARP gateway.
This ADR is Proposed and should not be implemented until the mobile client development begins. The current nginx-embedded approach remains valid for the MVP with a single web client.
Implementation is triggered when any of the following occurs:
ums.mobile-app project is created.IPartitionedRateLimiter integrates natively with UMS tenant context, enabling per-tenant rate limiting with no external tooling.ums.gateway) to the Docker Compose and future Kubernetes manifests.Yarp.ReverseProxy dependency already present in Ums.Presentation — it should be moved to the new gateway project.ums/src/apps/ums.web-app/nginx.conf| ADR Registry | Architecture Portal |