πŸ›‘οΈ Reverse-Proxy with OAuth2 Integration

The reverse-proxy forms the front line of the homelab’s application delivery architecture. It abstracts internal services, offloads TLS/SSL operations, provides intelligent load distribution, and now enforces centralized authentication via OAuth2 Proxy with Microsoft Entra ID for services that require identity-aware access. The following details how the Nginx reverse-proxy cluster is extended to use an OAuth2 proxy to provide single-sign on to web services.

A primary frontend node terminates HTTPS traffic, performs OAuth2 authentication checks when needed, and routes requests to one of two backend Nginx servers. Backend nodes provide redundancy, delivering highly available and fault-tolerant service delivery.


πŸ—οΈ Frontend Server Configuration (with OAuth2 Support)

The primary frontend Nginx server defines an upstream pool of backend proxy nodes:

http {
# BEGIN ANSIBLE MANAGED BLOCK
upstream backend {
  server rproxy-1:80 max_fails=3 fail_timeout=5s;
  server rproxy-2:80 backup;
}
# END ANSIBLE MANAGED BLOCK
}

Each HTTPS vhost then proxies authenticated traffic into the backend pool. If the site uses OAuth2, its configuration includes an authentication gate:

location = /oauth2/auth {
    proxy_pass http://127.0.0.1:4180; 
    proxy_set_header Host $http_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;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
}

location / {
    auth_request /oauth2/auth;
    error_page 401 = /oauth2/sign_in;

    proxy_pass http://backend;
}

The OAuth2 Proxy service running locally on the frontend authenticates the user via Microsoft Entra ID before backend servers ever see the request.


πŸ—„οΈ Backend Server Configuration

Backend Nginx servers are intentionally simple. They act only as reverse proxies to the internal application servers and do not terminate SSL or run OAuth2 logic:

location / {
    proxy_pass http://192.168.2.186:80;
}

Frontend nodes perform all heavy lifting β€” SSL, authentication, routing β€” while backend nodes focus purely on forwarding.


πŸ”„ Full Request Flow (OAuth2 + Reverse Proxy)

ASCII Architecture Diagram

                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                           β”‚        Internet Client       β”‚
                           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                           β”‚ HTTPS
                                           β–Ό
                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚    Frontend Nginx Reverse Proxy      β”‚
                        β”‚ (SSL termination + OAuth2 enforcementβ”‚
                        β”‚       + routing to backend)          β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 OAuth2 Sites Only                 β”‚ 
                         β”‚                         β”‚
                         β–Ό                         β”‚
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
                β”‚         OAuth2 Proxy       β”‚     β”‚  
                β”‚ (Microsoft Entra ID OIDC)  β”‚     β”‚ Normal Sites
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
                                β”‚ Token Issuance   β”‚
                                β–Ό                  β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
                     β”‚   Microsoft Entra ID   β”‚    β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
                         β”‚                         β–Ό
                         β–Ό  Authenticated, Header-Injected Traffic
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚                 Backend Reverse-Proxy Pool (HA)                β”‚
       β”‚   upstream backend { rproxy-1; rproxy-2 backup; }              β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚                     β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ rproxy-1   β”‚      β”‚ rproxy-2  β”‚ (Backup)
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
      β”‚                   β”‚
      β–Ό                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ App Server(s) β”‚    β”‚ App Server(s)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

❓ Why This Design

This architecture is intentionally layered to balance security, reliability, and maintainability.

1. Clear Separation of Responsibilities

This avoids complexity on backend nodes and makes identity management uniform.


2. Centralized Authentication

Only the frontend server runs OAuth2 Proxy instances, ensuring:


3. Minimal Exposure of Internal Network

Frontend handles all public traffic, so backend servers:


4. Simplified Automation

With configuration templates and per-domain OAuth2 Proxy services, the system is fully idempotent:


🟩 High Availability (HA) Characteristics

The architecture supports HA using lightweight but effective mechanisms:

Backend Redundancy

The upstream block:

upstream backend {
  server rproxy-1:80 max_fails=3 fail_timeout=5s;
  server rproxy-2:80 backup;
}

achieves:


Stateless OAuth2 Authentication

Because OAuth2 Proxy uses cookie-based sessions, the frontend can be scaled:


Frontend as the Control Plane

The frontend is the authoritative router and authentication gatekeeper.

Backend nodes never need to know:

The frontend injects all required headers: