TLS & cert-manager
When kubernetes.terminate_tls is enabled, Octopus terminates TLS on its listen port using
certificates sourced from your Gateway listeners' TLS Secrets — hot-reloaded as they rotate, and
selected per connection by SNI. This pairs naturally with cert-manager: point a Certificate at a
listener's Secret and Octopus picks it up automatically.
Enabling termination01
kubernetes:
enabled: true
terminate_tls: trueWith terminate_tls enabled the listen port serves HTTPS (SNI), not plain HTTP. The option is
ignored if static gateway.tls is configured — static file-based TLS takes precedence. So use
terminate_tls or gateway.tls, not both.
The operator needs RBAC to read Secrets and ReferenceGrants (the chart grants this). It then
runs a dedicated set of watchers over Gateway, TLS Secret, and ReferenceGrant resources.
Sourcing certificates from listeners02
Octopus extracts certificates from the terminating HTTPS/TLS listeners of your Gateway
resources:
Each listener's
tls.certificateRefs[](kindSecret) names the Secret holding the cert/key.A listener with
tls.mode: Passthroughcontributes no certificate (only terminating listeners do). PlainHTTPlisteners are ignored.The listener's
hostnamebecomes the SNI key for that certificate; a listener with nohostnameprovides the default (catch-all) certificate.The Secret must be a
kubernetes.io/tlsSecret — itstls.crtandtls.keyare read.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: octopus-gateway
namespace: infra
spec:
gatewayClassName: octopus
listeners:
- name: api
hostname: api.example.com
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: api-tls # kubernetes.io/tls Secret in `infra`
- name: web
hostname: www.example.com
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: web-tlsHot reload
The TLS reconciler tracks Gateways, Secret payloads, and ReferenceGrants. Whenever any of them changes it rebuilds the SNI resolver and atomically swaps it into the live acceptor. A certificate is loaded only once its Secret is actually present; if a listener references a Secret that doesn't exist yet, no cert is loaded until it appears, and removing the Secret drops the cert. This is what makes cert-manager rotations apply without a restart.
SNI multi-cert selection
Each terminating listener's hostname registers a certificate under that SNI name, so a single
Octopus instance fronting multiple HTTPS listeners serves the right certificate per connection. A
hostname-less listener sets the default certificate used when no SNI match is found.
Cross-namespace Secrets via ReferenceGrant03
A listener may reference a Secret in another namespace via certificateRefs[].namespace.
Same-namespace Secrets are always allowed; a cross-namespace Secret is only loaded if a
ReferenceGrant in the Secret's namespace permits it — from (group: gateway.networking.k8s.io,
kind: Gateway, namespace: <gateway namespace>) to (kind: Secret). Without a matching grant the
cert is denied (not loaded), and removing the grant revokes access on the next rebuild.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: octopus-gateway
namespace: prod
spec:
gatewayClassName: octopus
listeners:
- name: api
hostname: api.example.com
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: shared-tls
namespace: certs # cross-namespace
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-prod-gateway-certs
namespace: certs # lives in the SECRET's namespace
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: prod
to:
- group: ""
kind: SecretSee Gateway API for the full ReferenceGrant model.
cert-manager example04
Issue a certificate into the same Secret the listener references, and Octopus serves it. Below, a
Certificate writes api-tls in infra, which the listener above consumes:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-tls
namespace: infra
spec:
secretName: api-tls # the listener's certificateRefs[].name
dnsNames:
- api.example.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
group: cert-manager.ioWhen cert-manager renews and rewrites api-tls, the operator's Secret watch fires and the new
certificate is hot-swapped in — no pod restart required.
cert-manager resources (Certificate, Issuer/ClusterIssuer) belong to the cert-manager.io
API group and are reconciled by cert-manager, not Octopus. Octopus only consumes the resulting
kubernetes.io/tls Secret named by your Gateway listener.