Create an HTTPS listener on your API gateway. Then, your API gateway listens for secured HTTPS traffic on the specified port and hostname that you configure.

Before you begin

  1. Follow the Get started guide to install Gloo Gateway.

  2. Deploy a sample httpbin app.

  3. Make sure that you have the OpenSSL version of openssl, not LibreSSL. The openssl version must be at least 1.1.

    1. Check the openssl version that is installed. If you see LibreSSL in the output, continue to the next step.

        openssl version
        
    2. Install the OpenSSL version (not LibreSSL). For example, you might use Homebrew.

        brew install openssl
        
    3. Review the output of the OpenSSL installation for the path of the binary file. You can choose to export the binary to your path, or call the entire path whenever the following steps use an openssl command.

      • For example, openssl might be installed along the following path: /usr/local/opt/openssl@3/bin/
      • To run commands, you can append the path so that your terminal uses this installed version of OpenSSL, and not the default LibreSSL. /usr/local/opt/openssl@3/bin/openssl req -new -newkey rsa:4096 -x509 -sha256 -days 3650...
  4. Decide whether to set up a listener inline on the Gateway resource or as a separate ListenerSet resource. For more information, see the Listener overview.

    ListenerSets: This feature is available with Gloo Gateway 2.x or later. Also, you must install the experimental channel of the Kubernetes Gateway API at version 1.3 or later.

Create a TLS certificate

  1. Create a directory to store your TLS credentials in.

      mkdir example_certs
      
  2. Create a self-signed root certificate. The following command creates a root certificate that is valid for a year and can serve any hostname. You use this certificate to sign the server certificate for the gateway later. For other command options, see the OpenSSL docs.

      # root cert
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=any domain/CN=*' -keyout example_certs/root.key -out example_certs/root.crt
      
  3. Create an OpenSSL configuration that matches the HTTPS hostname you plan to use. Replace every example.com reference with the base domain that your listener serves.

      cat <<'EOF' > example_certs/gateway.cnf
    [ req ]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
    req_extensions = req_ext
    
    [ dn ]
    CN = *.example.com
    O = any domain
    
    [ req_ext ]
    subjectAltName = @alt_names
    
    [ alt_names ]
    DNS.1 = *.example.com
    DNS.2 = example.com
    EOF
      
  4. Use the configuration and root certificate to create and sign the gateway certificate.

      openssl req -new -nodes -keyout example_certs/gateway.key -out example_certs/gateway.csr -config example_certs/gateway.cnf
    openssl x509 -req -sha256 -days 365 \
      -CA example_certs/root.crt -CAkey example_certs/root.key -set_serial 0 \
      -in example_certs/gateway.csr -out example_certs/gateway.crt \
      -extfile example_certs/gateway.cnf -extensions req_ext
      
  5. Create a Kubernetes secret to store your server TLS certificate. You create the secret in the same cluster and namespace that the gateway is deployed to.

      kubectl create secret tls -n gloo-system https \
      --key example_certs/gateway.key \
      --cert example_certs/gateway.crt
    kubectl label secret https gateway=https --namespace gloo-system
      

Set up an HTTPS listener

Set up an HTTPS listener on your Gateway.

If you plan to set up your listener as part of a ListenerSet, keep the following considerations in mind. For more information, see ListenerSets (experimental).

  • This feature is available with Gloo Gateway 2.x or later.
  • You must install the experimental channel of the Kubernetes Gateway API at version 1.3 or later.
  1. Create a gateway resource with an HTTPS listener. To use the default Envoy-based Gloo Gateway proxy, set the gatewayClassName to gloo-gateway-v2. To use agentgateway, set the gatewayClassName to agentgateway.

  2. Check the status of the Gateway to make sure that your configuration is accepted. Note that in the output, a NoConflicts status of False indicates that the Gateway is accepted and does not conflict with other Gateway configuration.

      kubectl get gateway https -n gloo-system -o yaml
      
  3. Create an HTTPRoute resource for the httpbin app that is served by the gateway or ListenerSet that you created.

  4. Verify that the HTTPRoute is applied successfully.

      kubectl get httproute/httpbin-https -n httpbin -o yaml
      

    Example output: Notice in the status section that the parentRef is either the Gateway or the ListenerSet, depending on how you attached the HTTPRoute.

      ...
    status:
      parents:
      - conditions:
        - lastTransitionTime: "2025-04-29T20:48:51Z"
          message: ""
          observedGeneration: 3
          reason: Accepted
          status: "True"
          type: Accepted
        - lastTransitionTime: "2025-04-29T20:48:51Z"
          message: ""
          observedGeneration: 3
          reason: ResolvedRefs
          status: "True"
          type: ResolvedRefs
        controllerName: kgateway.dev/kgateway
      parentRef:
        group: gateway.networking.k8s.io
        kind: Gateway
        name: https
        namespace: gloo-system
      
  5. Verify that the listener now has a route attached.

  6. Get the external address of the gateway and save it in an environment variable.

  7. Send a request to the httpbin app and verify that you see the TLS handshake and you get back a 200 HTTP response code.

    Example output:

      * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *  CAfile: /etc/ssl/cert.pem
    *  CApath: none
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: CN=*; O=gateway
    *  start date: Nov  5 01:54:04 2023 GMT
    *  expire date: Nov  2 01:54:04 2033 GMT
    *  issuer: CN=*; O=root
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x15200e800)
    > GET /status/200 HTTP/2
    > Host: https.example.com
    > user-agent: curl/7.77.0
    > accept: */*
    > 
    *  Connection state changed (MAX_CONCURRENT_STREAMS == 2147483647)!
    < HTTP/2 200 
    HTTP/2 200 
    ...
      

Cleanup

You can remove the resources that you created in this guide.