# Two-Tier IIS Deployment Architecture ## Overview ROA2WEB uses a **2-tier IIS architecture** for production deployment: ``` Internet ↓ Public IIS Server (roa2web.romfast.ro) ↓ HTTPS reverse proxy Internal IIS Server (10.0.20.36) ↓ API proxy Backend Service (localhost:8000) ↓ Oracle Database ``` --- ## Architecture Components ### Tier 1: Public IIS Server (Edge/Gateway) **Hostname**: `roa2web.romfast.ro` **IP Address**: `10.0.20.122` **Role**: Public-facing reverse proxy **Location**: DMZ/Public network **Responsibilities**: - SSL/TLS termination (HTTPS) - Reverse proxy to internal server - Security headers - Public DNS endpoint **Configuration** (`web.config` pe serverul 10.0.20.122): ```xml ``` **Key Features**: - Root redirect: `https://roa2web.romfast.ro/` → `https://roa2web.romfast.ro/roa2web/` - All requests proxied to: `https://10.0.20.36/{REQUEST_PATH}` - Forwards client IP and protocol headers --- ### Tier 2: Internal IIS Server (Application Server) **IP Address**: `10.0.20.36` **Role**: Application host + API proxy **Location**: Internal network **Responsibilities**: - Serve Vue.js frontend static files - Proxy API requests to backend service - Handle uploads - IIS sub-application at `/roa2web` **Configuration** (`web.config` pe serverul 10.0.20.36 - `C:\inetpub\wwwroot\roa2web\web.config`): ```xml ``` **CRITICAL**: The internal server web.config must handle the `/roa2web/` prefix since requests arrive as: - `https://10.0.20.36/roa2web/api/auth/login` (NOT `/api/auth/login`) --- ### Backend Service (FastAPI) **Host**: `localhost` (internal server) **Port**: `8000` **Type**: Windows Service (NSSM) **Name**: `ROA2WEB-Backend` **Configuration** (`.env`): ```env HOST=127.0.0.1 PORT=8000 ENVIRONMENT=production ``` **Base Path**: `/api` (NOT `/roa2web/api`) The backend serves: - `/api/auth/login` - `/api/companies` - `/api/calendar` - etc. --- ## Request Flow Example ### Login Request Flow 1. **Client Browser** → `POST https://roa2web.romfast.ro/roa2web/api/auth/login` 2. **Public IIS** (roa2web.romfast.ro): - Receives: `/roa2web/api/auth/login` - Proxies to: `https://10.0.20.36/roa2web/api/auth/login` - Sets headers: `X-Forwarded-Proto: https`, `X-Forwarded-Host: roa2web.romfast.ro` 3. **Internal IIS** (10.0.20.36): - Receives: `/roa2web/api/auth/login` - Matches rule: `^roa2web/api/(.*)` - Extracts: `auth/login` - Proxies to: `http://localhost:8000/api/auth/login` 4. **Backend Service** (localhost:8000): - Receives: `/api/auth/login` - Processes request - Returns response --- ## Frontend Configuration ### Vite Build Configuration (`vite.config.js`) ```javascript export default defineConfig({ // Base path for IIS sub-application base: process.env.NODE_ENV === 'production' ? '/roa2web/' : '/', // Development proxy (NOT used in production) server: { proxy: { '/api': { target: 'http://localhost:8000', changeOrigin: true } } } }) ``` **IMPORTANT**: In production, `base: '/roa2web/'` ensures: - All asset paths: `/roa2web/assets/...` - Router base: `/roa2web/` - API calls: `/roa2web/api/...` (via axios baseURL) ### API Service Configuration (`src/App.vue`) ```javascript const authApi = axios.create({ baseURL: import.meta.env.BASE_URL + 'api', // Results in: '/roa2web/api' headers: { 'Content-Type': 'application/json' } }) ``` --- ## Common Issues & Troubleshooting ### Issue: 404 on API calls **Symptoms**: - Frontend loads correctly - API calls return 404 - Browser console: `POST https://roa2web.romfast.ro/roa2web/api/auth/login 404` **Possible Causes**: 1. **Internal server web.config missing `/roa2web/` prefix in match rules** ❌ **WRONG**: ```xml ``` ✅ **CORRECT**: ```xml ``` 2. **Backend service not running** Check on internal server (10.0.20.36): ```powershell Get-Service ROA2WEB-Backend Invoke-WebRequest http://localhost:8000/health ``` 3. **IIS ARR not enabled** On internal server (10.0.20.36): ```powershell # Install ARR Install-WindowsFeature -Name Web-ARR # Enable proxy Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" ` -Filter "system.webServer/proxy" ` -Name "enabled" ` -Value "True" ``` 4. **IIS sub-application not configured at `/roa2web`** The frontend must be deployed as IIS sub-application at path `/roa2web`, NOT as root site. ### Issue: Frontend loads but shows blank page **Symptoms**: - Browser shows white screen - Console error: `Failed to load module script` - Assets return 404 **Solution**: Check `base` in `vite.config.js` matches IIS sub-application path. ### Issue: CORS errors **Symptoms**: - API calls blocked by CORS policy - Console: `Access-Control-Allow-Origin` error **Solution**: Backend should see requests as same-origin (via IIS proxy), so CORS shouldn't apply. If you see CORS errors, the proxy is misconfigured. --- ## Deployment Checklist ### Public Server (roa2web.romfast.ro) - [ ] SSL certificate installed and valid - [ ] IIS ARR (Application Request Routing) installed - [ ] web.config configured with reverse proxy to 10.0.20.36 - [ ] Server variables enabled in IIS - [ ] Firewall allows HTTPS outbound to 10.0.20.36 ### Internal Server (10.0.20.36) - [ ] IIS installed and running - [ ] IIS ARR installed - [ ] IIS URL Rewrite module installed - [ ] Sub-application created at `/roa2web` - [ ] Frontend files deployed to `C:\inetpub\wwwroot\roa2web\` - [ ] web.config includes `/roa2web/` prefix in match rules - [ ] Backend service (ROA2WEB-Backend) running - [ ] Backend accessible at `http://localhost:8000/health` - [ ] Firewall allows HTTPS inbound from public server ### Backend Service - [ ] Windows Service created (NSSM) - [ ] Service set to auto-start - [ ] `.env` configured with correct Oracle credentials - [ ] Logs directory exists and writable - [ ] Health check returns 200 OK --- ## Testing Procedure ### 1. Test Backend Directly (on 10.0.20.36) ```powershell # Health check Invoke-WebRequest http://localhost:8000/health # API test (without auth) Invoke-WebRequest http://localhost:8000/api/health ``` ### 2. Test Internal IIS Proxy (on 10.0.20.36) ```powershell # Should proxy to backend Invoke-WebRequest https://localhost/roa2web/api/health # Should serve frontend Invoke-WebRequest https://localhost/roa2web/ ``` ### 3. Test Public Access (from any client) ```powershell # Frontend Invoke-WebRequest https://roa2web.romfast.ro/roa2web/ # API (will fail without auth, but should return 401 not 404) Invoke-WebRequest https://roa2web.romfast.ro/roa2web/api/health ``` ### 4. Test with Playwright (comprehensive) ```bash # Use Playwright to test full login flow ./start-playwright.sh ``` --- ## Monitoring & Logs ### Public Server Logs ```powershell # IIS logs Get-Content C:\inetpub\logs\LogFiles\W3SVC*\*.log -Tail 50 # Failed Request Tracing (if enabled) Get-ChildItem C:\inetpub\logs\FailedReqLogFiles ``` ### Internal Server Logs ```powershell # IIS logs Get-Content C:\inetpub\logs\LogFiles\W3SVC*\*.log -Tail 50 # Backend service logs Get-Content C:\inetpub\wwwroot\roa2web\logs\backend-stdout.log -Tail 50 -Wait Get-Content C:\inetpub\wwwroot\roa2web\logs\backend-stderr.log -Tail 50 ``` ### Backend Application Logs ```powershell # Application log Get-Content C:\inetpub\wwwroot\roa2web\backend\logs\app.log -Tail 100 ``` --- ## Security Considerations ### SSL/TLS - Public server handles SSL termination - Internal communication can use HTTPS (current) or HTTP (simpler) - Certificate management only needed on public server ### Firewall Rules **Public Server**: - Allow inbound: 443 (HTTPS) - Allow outbound: 443 to 10.0.20.36 **Internal Server**: - Allow inbound: 443 from public server IP only - No need to expose port 8000 externally (backend is localhost-only) ### Headers Public server sets forwarding headers: - `X-Forwarded-Proto: https` - Original protocol - `X-Forwarded-Host: roa2web.romfast.ro` - Original hostname - `X-Real-IP: {CLIENT_IP}` - Client IP address Backend can use these for logging and security. --- ## Version History | Version | Date | Changes | |---------|------|---------| | 1.0.0 | 2025-12-30 | Initial documentation | --- *Last Updated: 2025-12-30* *ROA2WEB Two-Tier IIS Deployment Architecture*