280 lines
8.2 KiB
YAML
280 lines
8.2 KiB
YAML
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= |