Nginx Reverse Proxy & Vhosts
The Nginx reverse proxy container (vps-proxy) acts as the single unified ingress point on ports 80 (HTTP) and 443 (HTTPS) for all domains and subdomains managed on the Hostinger VPS.
🏛️ Ingress Architecture
Nginx terminates TLS with Cloudflare 15-year certificates, validates client certificates for IoT telemetry (mTLS), enforces IP whitelisting for administration paths, and forwards requests across the Docker bridge network (vps-network).
/opt/vps-stack/proxy/├── nginx.conf # Master Nginx configuration├── allowed_ips.conf # Dynamic IP whitelist rules├── kong.yml # Declarative Kong routing definitions├── conf.d/ # Virtual host definitions (*.conf)│ ├── apps.conf # Webpage, Microservices, Flutter Web vhosts│ ├── converters.conf # Converter FastAPI backends (cloud.planovi.app)│ ├── docs.conf # Documentation portal reverse proxy to Cloudflare Pages│ └── supabase.conf # Kong, Auth, Studio, and Telemetry vhosts└── html/ # Custom branded error pages ├── 404.html # 404 Not Found template ├── 50x.html # 500 / 502 / 503 / 504 Error template └── default.html # Default root fallback landing page🌐 Virtual Host Configuration Catalog
1. Supabase Services (supabase.conf)
api.planovi.app&dev-api.planovi.app:- Standard REST/GraphQL/Auth API routed to Kong (
supabase-kong:8000). /deploy-webhooklocation proxied to the CI/CD service (vps-deployer:9000).
- Standard REST/GraphQL/Auth API routed to Kong (
supabase-studio.planovi.app&dev-supabase-studio.planovi.app:- Protected with
include /etc/nginx/allowed_ips.conf;. - Proxied to
supabase-studio:3000.
- Protected with
telemetry.planovi.app&dev-telemetry.planovi.app:- Configured with
ssl_verify_client on;andssl_client_certificate /etc/ssl/cloudflare/planovi-device-ca.pem;. - Forwards authenticated payloads directly to
supabase-edge-runtime:9000.
- Configured with
2. Client Web Applications (apps.conf)
planovi.app&www.planovi.app: Static HTML/JS marketing website served from/opt/vps-apps/webpage/prod.dev.planovi.app: Staging marketing website served from/opt/vps-apps/webpage/dev.dealflow.planovi.app&scheduler.planovi.app: Reverse proxied tophp-app:80(FastCGI PHP 8.3 FPM).panel.planovi.app&dev-panel.planovi.app: Flutter Web single page applications proxied toflutter-web:80with SPA HTML5 fallback (try_files $uri $uri/ /index.html;).
3. Converter Backends (converters.conf)
cloud.planovi.app: Proxied to Python FastAPI containerconverters-api-prod:8000.dev-cloud.planovi.app: Proxied to Python FastAPI containerconverters-api-dev:8000.
4. Docs Portal (docs.conf)
docs.planovi.app&dev-docs.planovi.app:- Protected by dynamic IP whitelist (
allowed_ips.conf). - Reverse proxies to Cloudflare Pages static edge deployments (
dev-docs-arq.pages.dev). - Uses dynamic DNS resolvers (
resolver 1.1.1.1 8.8.8.8 valid=300s;) to avoid startup halts if DNS propagates asynchronously.
- Protected by dynamic IP whitelist (
🎨 Branded Error Pages (html/)
When backends encounter upstream failures (e.g. during a service rebuild), Nginx intercepts error codes:
error_page 404 /404.html;error_page 500 502 503 504 /50x.html;These responsive HTML files offer user-friendly messaging styled with Planovi dark mode theme, contact links, and automatic retry diagnostics.
⚡ Zero-Downtime Reload
Whenever vhosts or whitelist rules are adjusted:
# Test Nginx configuration syntaxdocker exec vps-proxy nginx -t
# Hot-reload configuration without dropping active TCP connectionsdocker exec vps-proxy nginx -s reload