TLS Termination in Redpanda Console
TLS (Transport Layer Security) encrypts traffic between a client and a server. Setting up that encryption requires a certificate for the hostname the client asked for, along with the matching private key: during the TLS handshake the server presents the certificate and proves that it holds the key, and only then does either side send any HTTP.
TLS termination is the point in the network path where that handshake completes and traffic stops being encrypted. Whichever component terminates TLS is the one that:
-
Holds the certificate and the private key.
-
Clients validate when their browser shows a padlock for your hostname.
-
Must have the certificate renewed before it expires.
Everything downstream of that point receives plain HTTP, unless something re-encrypts it.
For Redpanda Console, the terminating component is either a gateway in front of Redpanda Console (a Gateway API gateway, reverse proxy, or load balancer) or the Redpanda Console process itself.
Terminating at a gateway is the preferred approach. It keeps certificate handling in one place, in front of the application, and Redpanda Console then runs with no TLS configuration at all. Terminate in Redpanda Console only when nothing in front of it can do the job.
|
On Kubernetes, configure TLS on a standalone Redpanda Console deployment, using either the The |
How TLS termination works
Terminate TLS at an upstream gateway
The diagram shows a Gateway API gateway on Kubernetes, but the shape is the same for any reverse proxy or load balancer. A request flows like this:
-
A browser opens a TLS connection to
console.example.comon port 443. The gateway answers the handshake with the certificate it holds, so the TLS session ends at the gateway. -
The gateway decrypts the request, matches its hostname and path against a route, and forwards it over a separate, plaintext HTTP connection to the Redpanda Console address on port 8080.
-
Redpanda Console receives ordinary HTTP. It has no certificate, no HTTPS listener, and no TLS configuration, so the rest of its deployment keeps its defaults.
This is the preferred approach:
-
The certificate lives on the gateway, in one place, where it can be issued and renewed automatically (by cert-manager on Kubernetes, for example). Redpanda Console never holds a certificate, and a renewal doesn’t touch Redpanda Console at all.
-
Redpanda Console keeps a single plaintext port, so nothing else about its deployment has to change. On Kubernetes, that means its Service, its route, and its health probes all keep their defaults.
-
Redpanda Console isn’t spending CPU on TLS handshakes.
-
A gateway is shared infrastructure. One certificate and one hostname policy can cover Redpanda Console alongside your other services.
Two consequences worth knowing:
-
The hop from the gateway to Redpanda Console is unencrypted. If that hop also has to be encrypted, it’s a job for the network between them (a service mesh on Kubernetes), rather than a Redpanda Console setting.
-
Redpanda Console only sends the HSTS header when its own TLS is enabled, so in this model set HSTS at the gateway instead.
Terminate TLS in Redpanda Console
Here Redpanda Console does the work itself, and runs two servers to do it. A request flows like this:
-
A browser opens a TLS connection on port 443. Redpanda Console answers the handshake with the certificate and key it reads from
certFilepathandkeyFilepath, so the TLS session ends inside the Redpanda Console process and nothing between the client and Redpanda Console ever sees plaintext. -
Redpanda Console’s HTTPS server, on
httpsListenPort, serves the request. -
A second, plaintext server on
listenPortaccepts any HTTP request and redirects it to the HTTPS address. It builds that address fromadvertisedHttpsListenPort, which is separate because the port clients reach may not be the port Redpanda Console listens on.
The certificate and key arrive as files, so renewal means updating whatever supplies those files and having Redpanda Console pick them up.
Use this only when nothing in front of Redpanda Console can terminate TLS for it, such as a binary running directly on a host. On Kubernetes it also costs extra configuration, because the certificate has to be mounted into the container and the Service has to be pointed at the HTTPS listener. See what else Kubernetes needs.
Use an upstream component for TLS termination
This is the preferred way to serve Redpanda Console over TLS. When an upstream component terminates TLS, it holds the certificate, decrypts incoming requests, and forwards plaintext HTTP to Redpanda Console. Whichever component you use, it must:
-
Terminate TLS with a certificate valid for the hostname that clients use.
-
Route traffic to the address and plaintext port of Redpanda Console, which is
8080by default. -
Pass along the original host header, so that Redpanda Console generates correct URLs from behind a proxy.
Redpanda Console needs no TLS configuration in this model. TLS is disabled by default, so usually there is nothing to change. To set it explicitly:
-
Standalone
-
Kubernetes
Add the following configuration to your /etc/redpanda/redpanda-console-config.yaml file:
server:
listenPort: 8080
tls:
enabled: false
Disable TLS in the Console resource or in the Redpanda Console Helm values:
-
Operator
-
Helm
apiVersion: cluster.redpanda.com/v1alpha2
kind: Console
metadata:
name: redpanda-console
namespace: redpanda
spec:
cluster:
clusterRef:
name: redpanda
config:
server:
listenPort: 8080
tls:
enabled: false
config:
server:
listenPort: 8080
tls:
enabled: false
Apply with:
helm upgrade --install redpanda-console redpanda/console -f console-values.yaml
Although Redpanda Console isn’t using TLS, the traffic remains secure because the upstream component handles TLS.
If you host Redpanda Console under a sub-path of your domain, such as https://my-company.com/redpanda/console, configure HTTP path rewrites in Redpanda Console.
Terminate TLS at an Envoy Gateway
On Kubernetes, the gateway is a Gateway API Gateway. The Gateway API is the successor to the Ingress API, and the widely used ingress-nginx controller retired in March 2026, so new deployments should route through a Gateway controller. These steps use Envoy Gateway; Istio, Cilium, and NGINX Gateway Fabric work the same way, with a different gatewayClassName.
Before you start, install the Gateway API CRDs and a Gateway controller. For versions and installation steps, see Configure External Access through Gateway API.
-
Create a Secret that holds the certificate and key for the Redpanda Console hostname, in the namespace where the Gateway runs. Use cert-manager to issue and renew it, or create it directly:
kubectl create secret tls console-tls \ --namespace gateway-system \ --cert=tls.crt --key=tls.key -
Create a Gateway with an HTTPS listener that terminates TLS with that Secret:
gateway.yamlapiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway namespace: gateway-system spec: gatewayClassName: eg (1) listeners: - name: https protocol: HTTPS port: 443 tls: mode: Terminate (2) certificateRefs: - name: console-tls allowedRoutes: namespaces: from: All (3)1 The GatewayClass name depends on your controller. Envoy Gateway installs eg.2 Terminatedecrypts traffic at the listener and forwards it to the backend in plaintext.3 The listener must allow routes from the namespace where Redpanda Console runs. Use from: Selectorto restrict which namespaces can attach. -
Apply the Gateway and confirm that the controller programmed the listener:
kubectl apply -f gateway.yaml kubectl get gateway my-gateway --namespace gateway-system \ -o jsonpath='{range .status.listeners[*]}{.name}: {range .conditions[*]}{.type}={.status} {end}{"\n"}{end}'The listener reports
Accepted=TrueandProgrammed=True. -
Attach Redpanda Console to the Gateway. Redpanda renders and maintains the HTTPRoute for you, pointing it at the plaintext Redpanda Console Service:
-
Operator
-
Helm
apiVersion: cluster.redpanda.com/v1alpha2 kind: Console metadata: name: redpanda-console namespace: redpanda spec: cluster: clusterRef: name: redpanda gateway: enabled: true parentRefs: - name: my-gateway namespace: gateway-system sectionName: https hostnames: - console.example.com path: / pathType: PathPrefixgateway: enabled: true parentRefs: - name: my-gateway namespace: gateway-system sectionName: https hostnames: - console.example.com path: / pathType: PathPrefix -
-
Point DNS for the hostname at the Gateway’s address, then confirm that the route attached and that the endpoint serves HTTPS:
kubectl get httproute --namespace redpanda curl -sI https://console.example.com | head -1
|
The |
Other upstream components
Outside Kubernetes, or where no Gateway controller is available, any reverse proxy or load balancer that meets the requirements in Use an upstream component for TLS termination works, including HAProxy and cloud HTTPS load balancers. Configure TLS termination on that component and forward plaintext HTTP to the Redpanda Console address and listenPort.
Use Redpanda Console for TLS termination
When you use Redpanda Console to terminate the TLS connection, Redpanda Console starts two HTTP servers:
-
An HTTPS server on the configured HTTPS port.
-
An HTTP server on the configured HTTP port which redirects HTTP requests to the HTTPS port.
-
Standalone
-
Kubernetes
Add the following configuration to your /etc/redpanda/redpanda-console-config.yaml file:
server:
# httpsListenPort defines the port on which Redpanda Console is listening for TLS connections, while advertisedHttpsListenPort defines the port that is advertised to clients, which may be different due to network configurations such as load balancers or proxies. advertisedHttpsListenPort is needed when redirecting a HTTP request to an HTTPS URL.
httpsListenPort: 443
advertisedHttpsListenPort: 443
listenPort: 8080
tls:
enabled: true
certFilepath: <path-to-cert>
keyFilepath: <path-to-key>
# AllowedOrigins is a list of origins that can send requests from a browser to the Redpanda Console
# API. By default, a same-site policy is enforced to prevent CSRF-attacks.
# Only in very specific deployment models you may need to change the secure default.
# For example, during development, it's common to have the API server and the client running on different ports of localhost, which are treated as different origins by browsers. In this case, you would need to set `allowedOrigins` to include the origin of your client's development server.
# allowedOrigins: []
Replace <path-to-cert> and <path-to-key> with the paths of your TLS certificate and key, respectively.
Configure TLS in the Console resource or in the Redpanda Console Helm values:
-
Operator
-
Helm
apiVersion: cluster.redpanda.com/v1alpha2
kind: Console
metadata:
name: redpanda-console
namespace: redpanda
spec:
cluster:
clusterRef:
name: redpanda
config:
server:
httpsListenPort: 443
advertisedHttpsListenPort: 443
listenPort: 8080
tls:
enabled: true
certFilepath: /etc/console/certs/tls.crt
keyFilepath: /etc/console/certs/tls.key
secretMounts:
- name: console-tls
secretName: console-tls
path: /etc/console/certs
service:
port: 443
targetPort: 443
config:
server:
httpsListenPort: 443
advertisedHttpsListenPort: 443
listenPort: 8080
tls:
enabled: true
certFilepath: /etc/console/certs/tls.crt
keyFilepath: /etc/console/certs/tls.key
secretMounts:
- name: console-tls
secretName: console-tls
path: /etc/console/certs
service:
port: 443
targetPort: 443
Apply with:
helm upgrade --install redpanda-console redpanda/console -f console-values.yaml
In this example, Redpanda Console is serving HTTPS traffic on port 443, where both httpsListenPort and advertisedHttpsListenPort are set to the same value. Any requests to the listenPort 8080 are redirected to the advertisedHttpsListenPort.
|
On Kubernetes, enabling TLS in the Redpanda Console configuration is not sufficient on its own. Redpanda Console terminates TLS inside the Pod, but by default the Service exposes only the plaintext listener, and the Ingress routes to that same Service port. The Kubernetes examples in this section therefore set three things beyond
|
If you want Redpanda Console to serve HTTPS on a non-standard port like 8081, but you want to present the URL to users as though it’s serving on the standard HTTPS port 443, you can set httpsListenPort to 8081 and advertisedHttpsListenPort to 443. This configuration might be useful in development or testing scenarios. For example, if Redpanda Console’s internal address is https://192.168.1.100:8081 but externally it’s accessed through https://public-address.com:443, set httpsListenPort to 8081 and advertisedHttpsListenPort to 443. Despite listening internally on 8081, Redpanda Console will generate URLs for clients using port 443.
If you host Redpanda Console under a sub-path of your domain, such as https://my-company.com/redpanda/console, configure HTTP path rewrites in Redpanda Console.
|
HTTP Strict Transport Security (HSTS)
The HTTP Strict Transport Security (HSTS) header tells a browser to reach a domain over HTTPS only:
Strict-Transport-Security: max-age=31536000
The HSTS header instructs web browsers to:
-
Always connect to Redpanda Console using HTTPS, never HTTP
-
Automatically upgrade any HTTP requests to HTTPS for the next 365 days (31536000 seconds)
-
Refuse connections if there are certificate errors or warnings
This behavior begins after the browser’s first successful HTTPS connection to Redpanda Console.
HSTS provides protection against:
-
Protocol downgrade attacks: Prevents attackers from forcing connections to use insecure HTTP
-
Accidental insecure connections: Users typing
http://in their browser are automatically redirected to HTTPS -
Session hijacking: Eliminates the risk window where HTTP traffic could be intercepted before redirect
Which component sends the header depends on where TLS terminates. Redpanda Console adds it automatically whenever its own TLS is enabled, so when a gateway terminates TLS instead, the gateway has to send it.
Set HSTS at an Envoy Gateway
The HTTPRoute that the Redpanda Operator and Helm chart render for you doesn’t accept route filters, so set the header on the Gateway rather than on the route. An Envoy Gateway ClientTrafficPolicy applies to every route on the Gateway it targets:
hsts.yamlapiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: console-hsts
namespace: gateway-system
spec:
targetRef: (1)
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
headers:
lateResponseHeaders:
set: (2)
- name: Strict-Transport-Security
value: max-age=31536000
| 1 | The Gateway to attach the policy to. The policy must be in the same namespace as that Gateway. |
| 2 | set replaces any existing value, so the header can’t end up duplicated. This is the same value Redpanda Console sends, so moving TLS termination to the Gateway doesn’t change what browsers see. |
If you write the HTTPRoute yourself instead of letting Redpanda render it, you can use the Gateway API ResponseHeaderModifier filter on the route instead. That filter is part of the Gateway API, so it works with any Gateway controller:
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
set:
- name: Strict-Transport-Security
value: max-age=31536000
For other upstream components, set the header wherever that component configures response headers. In every case, send it only over HTTPS: a browser ignores HSTS on a plaintext response.