Ingress & TLS (Kubernetes)

Expose KubeWatch on Kubernetes through ingress-nginx or an AWS ALB, with automatic HTTPS, or on the load balancer's own endpoint.

The Helm chart ships an Ingress that fronts the whole platform. Enable it with ingress.enabled=true. This page covers the two common setups, ingress-nginx (with cert-manager) and AWS ALB (with ACM), plus running on the load balancer's own endpoint without a custom domain.

How routing works

The Ingress splits traffic the same way the Docker/Caddy deployment does:

  • /api/*, /auth/*, /ws* go to the gateway
  • everything else (dashboard pages and assets) goes to the frontend

ingress.host is optional. Leave it empty (host: "") and the rule matches any Host header, so you can reach the app on the load balancer's own DNS name without owning a domain.

ingress-nginx (with cert-manager)

Requires an ingress-nginx controller and (for automatic HTTPS) cert-manager with a ClusterIssuer.

# values.yaml
ingress:
  enabled: true
  className: nginx
  host: kubewatch.your-company.com
  tls: true
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    # Keep live-log SSE streams and WebSockets alive (default nginx timeout is 60s):
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"

With tls: true, the chart adds a TLS block backed by the {release}-tls Secret, which cert-manager fills once it issues the certificate for host. Point your domain's DNS at the ingress-nginx load balancer, then apply:

helm upgrade --install kubewatch \
  https://raw.githubusercontent.com/lloyd-theophilus/kubewatch-releases/main/kubewatch.tgz \
  -f values.yaml

AWS ALB (with ACM)

Requires the AWS Load Balancer Controller. TLS is terminated at the ALB using an ACM certificate, so you do NOT set ingress.tls, and there is no Kubernetes TLS Secret. The certificate is referenced by annotation instead.

# values.yaml
ingress:
  enabled: true
  className: alb
  host: kubewatch.your-company.com   # or "" to use the ALB's own DNS name
  tls: false                          # ALB terminates TLS via ACM, not a K8s Secret
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:REGION:ACCOUNT:certificate/ID
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    # Raise the ALB idle timeout so live-log SSE streams / WebSockets aren't cut at 60s:
    alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=3600

After helm upgrade, get the ALB's DNS name and point your domain at it with a CNAME (or a Route 53 alias):

kubectl get ingress kubewatch-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
The ACM certificate must cover the hostname you use (the domain you CNAME to the ALB). ACM does not issue certificates for a raw ALB DNS name, so for HTTPS you need a domain. To try it over the ALB endpoint first, drop the HTTPS listener and use `listen-ports: '[{"HTTP":80}]'`.

No domain: the load balancer endpoint

To reach the app without a custom domain, leave the host empty:

ingress:
  enabled: true
  className: nginx   # or alb
  host: ""           # match any Host, serve on the LB's own DNS name
  tls: false

Then open the load balancer's address:

  • ingress-nginx: the external IP/hostname of the ingress-nginx-controller Service (kubectl get svc -n ingress-nginx).
  • AWS ALB: the ALB DNS name from the kubectl get ingress command above.
Serving on a bare load-balancer endpoint means plain HTTP (no certificate). Use it for testing only. Put a domain and TLS in front before exposing the platform to real users, so sessions and credentials aren't sent in the clear.

Live logs and WebSockets

The dashboard streams container/pod logs over long-lived HTTP (SSE) and uses a WebSocket for live updates. Load balancers cut idle connections by default (often 60s), which shows up as logs that stop after a minute. The timeout annotations above (proxy-read-timeout for nginx, idle_timeout.timeout_seconds for ALB) keep those streams open, so set them whenever you enable ingress.

Verify

kubectl get ingress
# Then, from a machine that can resolve the host:
curl -ksS https://kubewatch.your-company.com/api/v1/health   # gateway → 200
curl -ksS https://kubewatch.your-company.com/                 # dashboard HTML

If /api/v1/health returns 200 but / does not serve the dashboard, the Ingress isn't routing non-API paths to the frontend, double-check you're on a chart version that splits the routes (this page's behavior).