apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wifi-densepose-ingress namespace: wifi-densepose labels: app: wifi-densepose component: ingress annotations: # NGINX Ingress Controller annotations kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/backend-protocol: "HTTP" # Rate limiting nginx.ingress.kubernetes.io/rate-limit: "100" nginx.ingress.kubernetes.io/rate-limit-window: "1m" nginx.ingress.kubernetes.io/rate-limit-connections: "10" # CORS configuration nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://wifi-densepose.com,https://app.wifi-densepose.com" nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST,PUT,DELETE,OPTIONS" nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type,Authorization,X-Requested-With" nginx.ingress.kubernetes.io/cors-allow-credentials: "true" # Security headers nginx.ingress.kubernetes.io/configuration-snippet: | add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: https:;" always; # Load balancing nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr" nginx.ingress.kubernetes.io/load-balance: "round_robin" # Timeouts nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" nginx.ingress.kubernetes.io/proxy-send-timeout: "30" nginx.ingress.kubernetes.io/proxy-read-timeout: "30" # Body size nginx.ingress.kubernetes.io/proxy-body-size: "10m" # Certificate management (cert-manager) cert-manager.io/cluster-issuer: "letsencrypt-prod" cert-manager.io/acme-challenge-type: "http01" spec: tls: - hosts: - wifi-densepose.com - api.wifi-densepose.com - app.wifi-densepose.com secretName: wifi-densepose-tls rules: - host: wifi-densepose.com http: paths: - path: / pathType: Prefix backend: service: name: nginx-service port: number: 80 - path: /health pathType: Exact backend: service: name: wifi-densepose-service port: number: 8000 - host: api.wifi-densepose.com http: paths: - path: / pathType: Prefix backend: service: name: wifi-densepose-service port: number: 8000 - path: /api pathType: Prefix backend: service: name: wifi-densepose-service port: number: 8000 - path: /docs pathType: Prefix backend: service: name: wifi-densepose-service port: number: 8000 - path: /metrics pathType: Exact backend: service: name: wifi-densepose-service port: number: 8080 - host: app.wifi-densepose.com http: paths: - path: / pathType: Prefix backend: service: name: nginx-service port: number: 80 --- # WebSocket Ingress (separate for sticky sessions) apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wifi-densepose-websocket-ingress namespace: wifi-densepose labels: app: wifi-densepose component: websocket-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # WebSocket specific configuration nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr" nginx.ingress.kubernetes.io/affinity: "cookie" nginx.ingress.kubernetes.io/affinity-mode: "persistent" nginx.ingress.kubernetes.io/session-cookie-name: "wifi-densepose-ws" nginx.ingress.kubernetes.io/session-cookie-expires: "3600" nginx.ingress.kubernetes.io/session-cookie-max-age: "3600" nginx.ingress.kubernetes.io/session-cookie-path: "/ws" # WebSocket upgrade headers nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $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_cache_bypass $http_upgrade; cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - ws.wifi-densepose.com secretName: wifi-densepose-ws-tls rules: - host: ws.wifi-densepose.com http: paths: - path: /ws pathType: Prefix backend: service: name: wifi-densepose-websocket port: number: 8000 --- # Internal Ingress for monitoring and admin access apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wifi-densepose-internal-ingress namespace: wifi-densepose labels: app: wifi-densepose component: internal-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # IP whitelist for internal access nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" # Basic auth for additional security nginx.ingress.kubernetes.io/auth-type: "basic" nginx.ingress.kubernetes.io/auth-secret: "wifi-densepose-basic-auth" nginx.ingress.kubernetes.io/auth-realm: "WiFi-DensePose Internal Access" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - internal.wifi-densepose.com secretName: wifi-densepose-internal-tls rules: - host: internal.wifi-densepose.com http: paths: - path: /metrics pathType: Prefix backend: service: name: wifi-densepose-internal port: number: 8080 - path: /health pathType: Prefix backend: service: name: wifi-densepose-internal port: number: 8000 - path: /api/v1/status pathType: Exact backend: service: name: wifi-densepose-internal port: number: 8000 --- # Certificate Issuer for Let's Encrypt apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@wifi-densepose.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx - dns01: cloudflare: email: admin@wifi-densepose.com apiTokenSecretRef: name: cloudflare-api-token key: api-token --- # Staging Certificate Issuer for testing apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: server: https://acme-staging-v02.api.letsencrypt.org/directory email: admin@wifi-densepose.com privateKeySecretRef: name: letsencrypt-staging solvers: - http01: ingress: class: nginx --- # Basic Auth Secret for internal access apiVersion: v1 kind: Secret metadata: name: wifi-densepose-basic-auth namespace: wifi-densepose type: Opaque data: # Generated with: htpasswd -nb admin password | base64 # Default: admin:password (change in production) auth: YWRtaW46JGFwcjEkSDY1dnFkNDAkWGJBTHZGdmJQSVcuL1pLLkNPeS4wLwo=