๐งฉ Problem Summary
We encountered an issue while setting up HTTPS traffic from an AWS Application Load Balancer (ALB) to our NGINX Ingress Controller deployed in a private EKS cluster. Specifically:
- โ
HTTPS โ HTTP
(ALB terminates SSL, sends plain HTTP to NGINX): Worked - โ
HTTPS โ HTTPS
(ALB forwards SSL directly to NGINX): Did not work
โ ๏ธ Symptoms
- ALB health checks were failing on port
443
- Browsers showed
SSL handshake
orbad certificate
errors - NGINX logs showed no SSL negotiation happening
- Direct access to the NGINX NodePort via HTTPS worked fine
โ๏ธ Initial Setup
โ ALB Listener (Working Case)
- Port 443 โ Target group on port 80 (HTTP)
- SSL is terminated at ALB level
This worked because the NGINX Ingress was listening on HTTP internally, and the ALB decrypted HTTPS before forwarding it.
โ ALB Listener (Failing Case)
- Port 443 โ Target group on port 443 (HTTPS)
- SSL passthrough from ALB to NGINX Ingress
This failed because NGINX Ingress was not configured to present a certificate by default when the ALB initiated a TLS handshake.
๐ ๏ธ The Fix
To solve this, we added the following flag to the NGINX Ingress Controller deployment:
--default-server-tls-secret=aptia-ov3-dev/ov3-fe-dev-tls
๐ What This Does
- Configures the default SSL certificate that NGINX Ingress will serve during TLS handshakes.
- This is essential when:
- The ALB is configured for HTTPS in the target group.
- The Ingress Controller receives TLS connections directly.
- No specific Ingress rule is matched yet (like for health checks or root path).
๐ Why Is This Required?
By default, NGINX Ingress only presents a certificate if a matching TLS Ingress resource is hit. However, during:
- ALB health checks (to
/
), - or initial TLS handshakes before routing,
NGINX has no cert to present unless a default is defined.
๐งพ Sample Secret Definition
Make sure you have a Kubernetes TLS secret created like:
apiVersion: v1
kind: Secret
metadata:
name: ov3-fe-dev-tls
namespace: aptia-ov3-dev
type: kubernetes.io/tls
data:
tls.crt: <base64_cert>
tls.key: <base64_key>
๐งฑ Updated Ingress Controller Args
In your Helm values or manifest:
controller:
extraArgs:
default-server-tls-secret: "aptia-ov3-dev/ov3-fe-dev-tls"
Or, if you’re using raw manifests:
args:
- --default-server-tls-secret=aptia-ov3-dev/ov3-fe-dev-tls
โ Final Result
After setting the --default-server-tls-secret
:
- ALB to NGINX via HTTPS โ HTTPS worked correctly.
- Health checks succeeded.
- Browsers received valid TLS responses.
- No more handshake or certificate errors.
๐ง Key Takeaways
Lesson | Explanation |
---|---|
ALB cannot connect via HTTPS unless NGINX has a default cert | Because TLS handshake fails without a cert |
NGINX must serve a certificate even when no Ingress is matched | Required for root path/health checks |
Always define --default-server-tls-secret when using HTTPS passthrough | Especially with ALBs on private EKS clusters |