Expose Postgres using Traefik V3

@joseftw Thank you for this post! This helped me with my solve my issue exposing the postgres service via IngressRouteTCP which is only the first half of getting this working with TLS. I might've figured out the second half of this.

For the first half of the problem, exposing the postgres port, I had to tweak your answer for the expose due to updates to the Traefik Helm Chart, from:

postgress:
  ...
  expose: true

to:

  postgres:
    ...
    expose:
      default: true

This allowed me connect and test the port using:

nc -zv pg-authentik-rw.example.com 5432

The second hand of the problem has to deal with ALPN Protocol Mismatch. When trying to connect to my posgres instance from pgadmin, i was getting the following error:

connection failed: connection to server at "pg-authentik-rw.example.com", port 5432 failed: SSL error: tlsv1 alert no
application protocol

To solve this issue and be able to connect to postgres using TLS, we need to configure the TLSOption to remove ALPN Protocols.

First, we need to create a TLSOption resource in Kubernetes:

apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
  name: no-alpn
  namespace: authentik
spec:
  alpnProtocols: []

Setting the alpnProtocols: [] to an empty list allows us to remove the default options that are set with TLSOption.

Then in the IngressRouteTCP we need to add this option to the tls.options and reapply the changes

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: ingress-tcp-pg-authentik-rw
  namespace: authentik
  annotations: 
    kubernetes.io/ingress.class: traefik-external
spec:
  entryPoints:
    - postgres
  routes:
    - match: HostSNI(`pg-authentik-rw.example.com`)
      services:
        - name: pg-authentik-rw
          port: 5432
  tls:
    secretName: prod-example-com-tls
    options:
      name: no-alpn

This allowed me to connect to the postgres using pgadmin with SSL.

Additional Note - This uses a wildcard cert with letsencrypt to allow TLS to cloudnative-pg postgres instance, which is why I use HostSNI(`domain`) and NOT HostSNI(`*`) I believe the latter option is to make Traeffik as a passthrough and let the application handle TLS, with the passthrough: true option.