How to configure the helm chart include TLS termination (https) into OWUI pod #31

Closed
opened 2026-02-15 19:15:36 -05:00 by yindo · 7 comments
Owner

Originally created by @brokedba on GitHub (Sep 2, 2024).

I want to expose my open web ui in the cloud using TLS termination (since the Ip address is not localhost it is not recognized as safe so no mic or device can accessed from the browser).

I have the below values for the OpnWebUI helm chart and I think I secrewed it up a bit between the ingress and the loadbalancer service. I want to add a tsl secret and get the https termination accessible. I assume I need to keep the service clusterIP and add a TLS secret to the ingress to forward http traffic to https but really benefit from your help.
My K8 is in Oracle cloud OCI btw.


# Open WebUI Helm values
nameOverride: ""

ollama:
  enabled: false

ollamaUrls:
  - "http://ollama.ollama.svc.cluster.local:11434"

pipelines:
  enabled: true

ingress:
  enabled: true
  class: "nginx"
  annotations:
    kubernetes.io/ingress.class: nginx
  hosts:
    - host: openwebui.domain
      paths:
        - path: /
          pathType: Prefix
  tls: false

persistence:
  enabled: true
  size: 2Gi

service:
  type: LoadBalancer  # Change service type to LoadBalancer
  annotations:
    service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"  # Specify the shape of the LB
    service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10"
    service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "100"
    service.beta.kubernetes.io/oci-load-balancer-internal: "false"  # Set to "false" if you need an external LB
  port: 80
  containerPort: 8080
  loadBalancerIP: ""  # You can leave this empty or specify a static IP if required
  labels: {}
  loadBalancerClass: ""

extraEnvVars:
  - name: OPENAI_API_KEY
    value: "0p3n-w3bu!"

podSecurityContext: {}
containerSecurityContext: {}
Originally created by @brokedba on GitHub (Sep 2, 2024). I want to expose my open web ui in the cloud using TLS termination (since the Ip address is not localhost it is not recognized as safe so no mic or device can accessed from the browser).  I have the below values for the [OpnWebUI helm chart ](https://github.com/open-webui/helm-charts/blob/main/charts/open-webui/values.yaml) and I think I secrewed it up a bit between the ingress and the loadbalancer service. I want to add a tsl secret and get the https termination accessible. I assume I need to keep the service `clusterIP` and add a TLS secret to the ingress to forward http traffic to https but really benefit from your help. My K8 is in Oracle cloud OCI btw.  ``` # Open WebUI Helm values nameOverride: ""  ollama: enabled: false  ollamaUrls: - "http://ollama.ollama.svc.cluster.local:11434"  pipelines: enabled: true  ingress: enabled: true class: "nginx" annotations: kubernetes.io/ingress.class: nginx hosts: - host: openwebui.domain paths: - path: / pathType: Prefix tls: false  persistence: enabled: true size: 2Gi  service: type: LoadBalancer # Change service type to LoadBalancer annotations: service.beta.kubernetes.io/oci-load-balancer-shape: "flexible" # Specify the shape of the LB service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10" service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "100" service.beta.kubernetes.io/oci-load-balancer-internal: "false" # Set to "false" if you need an external LB port: 80 containerPort: 8080 loadBalancerIP: "" # You can leave this empty or specify a static IP if required labels: {} loadBalancerClass: ""  extraEnvVars: - name: OPENAI_API_KEY value: "0p3n-w3bu!"  podSecurityContext: {} containerSecurityContext: {} ```
yindo added the enhancement label 2026-02-15 19:15:36 -05:00
yindo closed this issue 2026-02-15 19:15:36 -05:00
Author
Owner

@westbrook-ai commented on GitHub (Sep 2, 2024):

Hey @brokedba, these are the relevant lines of the Helm chart for TLS: https://github.com/open-webui/helm-charts/blob/main/charts/open-webui/templates/ingress.yaml#L17-L21

If you have a TLS secret to use created on your cluster already, it looks like you need to set the tls value to true, and set the .Values.ingress.existingSecret value to the name of that secret in your K8s cluster. This should get your TLS termination working.

If you need to try a different approach, I see Oracle has a guide to set up an Nginx ingress controller on their Kubernetes service, so this might be worth the read: https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupingresscontroller.htm. I'm doing something similar to this approach on my clusters using the AWS ALB Ingress Controller.

Please let me know if you find a fix, or any further issues with the chart while trying to implement one!

@westbrook-ai commented on GitHub (Sep 2, 2024): Hey @brokedba, these are the relevant lines of the Helm chart for TLS: https://github.com/open-webui/helm-charts/blob/main/charts/open-webui/templates/ingress.yaml#L17-L21 If you have a TLS secret to use created on your cluster already, it looks like you need to set the `tls` value to `true`, and set the `.Values.ingress.existingSecret` value to the name of that secret in your K8s cluster. This should get your TLS termination working. If you need to try a different approach, I see Oracle has a guide to set up an Nginx ingress controller on their Kubernetes service, so this might be worth the read: https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupingresscontroller.htm. I'm doing something similar to this approach on my clusters using the AWS ALB Ingress Controller. Please let me know if you find a fix, or any further issues with the chart while trying to implement one!
Author
Owner

@brokedba commented on GitHub (Sep 2, 2024):

Hi @0xThresh , the ingress controller was actually the default nginx.
https actually works already as by default the ingress class chosen is nginx . The ingress controller service is a loadbalancer and the ingress of the openwebui shares the same IP.

kubectl describe ingress -n open-webui
Name:             open-webui
Labels:           app.kubernetes.io/component=open-webui
                  app.kubernetes.io/instance=open-webui
                  app.kubernetes.io/managed-by=Helm
                  app.kubernetes.io/version=0.3.13
                  helm.sh/chart=open-webui-3.1.7
Namespace:        open-webui
Address:          40.233.69.156     <------- ingress controller service => loadBalancer 
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   open-webui:http (10.244.0.227:8080)
Annotations:  kubernetes.io/ingress.class: nginx
              meta.helm.sh/release-name: open-webui
              meta.helm.sh/release-namespace: open-webui
              ```
              

ingress-controller has the same external IP

kubectl describe svc ingress-nginx-controller -n cluster-tools
Name:                     ingress-nginx-controller
Namespace:                cluster-tools
Labels:                   app.kubernetes.io/component=controller
                          app.kubernetes.io/instance=ingress-nginx
                          app.kubernetes.io/managed-by=Helm
                          app.kubernetes.io/name=ingress-nginx
                          app.kubernetes.io/part-of=ingress-nginx
                          app.kubernetes.io/version=1.7.1
                          helm.sh/chart=ingress-nginx-4.6.1
Annotations:              meta.helm.sh/release-name: ingress-nginx
                          meta.helm.sh/release-namespace: cluster-tools
                          service.beta.kubernetes.io/oci-load-balancer-shape: flexible
                          service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: 100
                          service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: 10
Selector:                 app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.96.108.219
IPs:                      10.96.108.219
LoadBalancer Ingress:     40.233.69.156    <------------------- same with openwebUi ingress
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  32224/TCP
Endpoints:                10.244.1.18:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  30175/TCP
Endpoints:                10.244.1.18:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

  • this is just by choosing the default nginx ingressclass in the helm chart.
    -I think it's probably the default ingress controller which creates a self signed certificate.

Regarding tls secret ingress cofig
when I tried to create a ingress with a tls existing secret , I had the below error . I'm probably clueless of FQDN tls fundamentals , I tried with both empty and random domain value so try resolving the HTTPS://ingress_IP, but RFC 1123 didn't like it.

...
ingress:
  enabled: true
  class: "nginx"
  annotations:
    kubernetes.io/ingress.class: nginx
  hosts:
    - host: openwebui.com
      paths:
        - path: /
          pathType: Prefix
  tls: true
  existingSecret: "openwebui-tls-secret"
...
Error: UPGRADE FAILED: cannot patch "open-webui" with kind Ingress: Ingress.networking.k8s.io "open-webui" is invalid: spec.tls[0].hosts[0]: Invalid value: "": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
-- both empty and full values had the same outcome
@brokedba commented on GitHub (Sep 2, 2024): Hi @0xThresh , the ingress controller was actually the default nginx. https actually works already as by default the ingress class chosen is nginx . The ingress controller service is a loadbalancer and the ingress of the openwebui shares the same IP. ``` kubectl describe ingress -n open-webui Name: open-webui Labels: app.kubernetes.io/component=open-webui app.kubernetes.io/instance=open-webui app.kubernetes.io/managed-by=Helm app.kubernetes.io/version=0.3.13 helm.sh/chart=open-webui-3.1.7 Namespace: open-webui Address: 40.233.69.156 <------- ingress controller service => loadBalancer Ingress Class: nginx Default backend: <default> Rules: Host Path Backends ---- ---- -------- * / open-webui:http (10.244.0.227:8080) Annotations: kubernetes.io/ingress.class: nginx meta.helm.sh/release-name: open-webui meta.helm.sh/release-namespace: open-webui ``` ``` ingress-controller has the same external IP ``` kubectl describe svc ingress-nginx-controller -n cluster-tools Name: ingress-nginx-controller Namespace: cluster-tools Labels: app.kubernetes.io/component=controller app.kubernetes.io/instance=ingress-nginx app.kubernetes.io/managed-by=Helm app.kubernetes.io/name=ingress-nginx app.kubernetes.io/part-of=ingress-nginx app.kubernetes.io/version=1.7.1 helm.sh/chart=ingress-nginx-4.6.1 Annotations: meta.helm.sh/release-name: ingress-nginx meta.helm.sh/release-namespace: cluster-tools service.beta.kubernetes.io/oci-load-balancer-shape: flexible service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: 100 service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: 10 Selector: app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx Type: LoadBalancer IP Family Policy: SingleStack IP Families: IPv4 IP: 10.96.108.219 IPs: 10.96.108.219 LoadBalancer Ingress: 40.233.69.156 <------------------- same with openwebUi ingress Port: http 80/TCP TargetPort: http/TCP NodePort: http 32224/TCP Endpoints: 10.244.1.18:80 Port: https 443/TCP TargetPort: https/TCP NodePort: https 30175/TCP Endpoints: 10.244.1.18:443 Session Affinity: None External Traffic Policy: Cluster Events: <none> ``` - this is just by choosing the default nginx ingressclass in the helm chart. -I think it's probably the default ingress controller which creates a self signed certificate. **Regarding tls secret ingress cofig** when I tried to create a ingress with a tls existing secret , I had the below error . I'm probably clueless of FQDN tls fundamentals , I tried with both empty and random domain value so try resolving the HTTPS://ingress_IP, but RFC 1123 didn't like it. ``` ... ingress: enabled: true class: "nginx" annotations: kubernetes.io/ingress.class: nginx hosts: - host: openwebui.com paths: - path: / pathType: Prefix tls: true existingSecret: "openwebui-tls-secret" ... ``` ``` Error: UPGRADE FAILED: cannot patch "open-webui" with kind Ingress: Ingress.networking.k8s.io "open-webui" is invalid: spec.tls[0].hosts[0]: Invalid value: "": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*') -- both empty and full values had the same outcome ```
Author
Owner

@westbrook-ai commented on GitHub (Sep 2, 2024):

If you check the chart's ingress.yaml file, you'll see that the host value is used to populate the TLS host and the typical routes host. You're trying to pass the whole hosts block which isn't a valid value for the chart, and that explains why you're getting an error stating that the hostname is "" since the host value isn't being set in the values you sent.

I think these values will work better:

ingress:
  enabled: true
  class: "nginx"
  annotations:
    kubernetes.io/ingress.class: "nginx"
  host: openwebui.domain
  tls: true
  existingSecret: "openwebui-tls-secret"
@westbrook-ai commented on GitHub (Sep 2, 2024): If you check the chart's `ingress.yaml` file, you'll see that the `host` value is used to populate the TLS host and the typical routes host. You're trying to pass the whole `hosts` block which isn't a valid value for the chart, and that explains why you're getting an error stating that the hostname is `""` since the `host` value isn't being set in the values you sent. I think these values will work better: ``` ingress: enabled: true class: "nginx" annotations: kubernetes.io/ingress.class: "nginx" host: openwebui.domain tls: true existingSecret: "openwebui-tls-secret" ```
Author
Owner

@brokedba commented on GitHub (Sep 3, 2024):

If you check the chart's ingress.yaml file, you'll see that the host value is used to populate the TLS host and the typical routes host. You're trying to pass the whole hosts block which isn't a valid value for the chart, and that explains why you're getting an error stating that the hostname is "" since the host value isn't being set in the values you sent.

I think these values will work better:

ingress:
  enabled: true
  class: "nginx"
  annotations:
    kubernetes.io/ingress.class: "nginx"
  host: openwebui.domain
  tls: true
  existingSecret: "openwebui-tls-secret"

You are right , somehow I use the syntax with hosts without knowing how it ended there . Probably a copy paste gone wrong (from another helm chart , ollama ?) .
However , even if the error is gone I now have conflict with the ingress IP with error 404.

I have to remove the tls config again and see if I can recover the TLS termination with that same IP.

kubectl get ingress -A
NAMESPACE       NAME         CLASS   HOSTS                    ADDRESS         PORTS     AGE
ollama          ollama       nginx   ollama.domain            40.233.69.156   80        46h
open-webui      open-webui   nginx   openwebui.com            40.233.69.156   80, 443   6h16m

kubectl get svc -A | grep ingress
NAMESPACE          NAME                                  TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
cluster-tools      ingress-nginx-controller              LoadBalancer   10.96.108.219   40.233.69.156   80:32224/TCP,443:30175/TCP   53d
@brokedba commented on GitHub (Sep 3, 2024): > If you check the chart's `ingress.yaml` file, you'll see that the `host` value is used to populate the TLS host and the typical routes host. You're trying to pass the whole `hosts` block which isn't a valid value for the chart, and that explains why you're getting an error stating that the hostname is `""` since the `host` value isn't being set in the values you sent. > > I think these values will work better: > > ``` > ingress: > enabled: true > class: "nginx" > annotations: > kubernetes.io/ingress.class: "nginx" > host: openwebui.domain > tls: true > existingSecret: "openwebui-tls-secret" > ``` You are right , somehow I use the syntax with hosts without knowing how it ended there . Probably a copy paste gone wrong (from another helm chart , ollama ?) . However , even if the error is gone I now have conflict with the ingress IP with error 404. I have to remove the tls config again and see if I can recover the TLS termination with that same IP. ``` kubectl get ingress -A NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE ollama ollama nginx ollama.domain 40.233.69.156 80 46h open-webui open-webui nginx openwebui.com 40.233.69.156 80, 443 6h16m kubectl get svc -A | grep ingress NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cluster-tools ingress-nginx-controller LoadBalancer 10.96.108.219 40.233.69.156 80:32224/TCP,443:30175/TCP 53d ```
Author
Owner

@brokedba commented on GitHub (Sep 3, 2024):

@0xThresh
the only way to avoid the nginx conflict (404 not found) in my K8 config on OCI is to remove the host value all together .

ingress:
  enabled: true
  class: "nginx"
  annotations:
  kubernetes.io/ingress.class: nginx
  host: ""
  tls: false
  existingSecret: ""

This fixed it and I could use the IP of the nginx controller to access openwebui service (via redirection).
I'll leave it like this . I'm sure every cloud has it's own particularity but on OCI , I don't need to define a tls cert or host if the class is the default nginx which is fine by me .

@brokedba commented on GitHub (Sep 3, 2024): @0xThresh the only way to avoid the nginx conflict (404 not found) in my K8 config on OCI is to remove the host value all together . ``` ingress: enabled: true class: "nginx" annotations: kubernetes.io/ingress.class: nginx host: "" tls: false existingSecret: "" ``` This fixed it and I could use the IP of the nginx controller to access openwebui service (via redirection). I'll leave it like this . I'm sure every cloud has it's own particularity but on OCI , I don't need to define a tls cert or host if the class is the default nginx which is fine by me .
Author
Owner

@westbrook-ai commented on GitHub (Sep 12, 2024):

Thanks for reporting back. We can look at re-working the ingress in the template to only define the host if it's included as a value to help any future OCI users.

@westbrook-ai commented on GitHub (Sep 12, 2024): Thanks for reporting back. We can look at re-working the ingress in the template to only define the host if it's included as a value to help any future OCI users.
Author
Owner

@brokedba commented on GitHub (Nov 30, 2024):

Thanks for reporting back. We can look at re-working the ingress in the template to only define the host if it's included as a value to help any future OCI users.

What I noticed in other addon helm based installation in OCI is that there if the microservice is expecting a path i.e /webui
the ingress can be created with a host matching it.

resource "helm_release" "grafana" {
 name       = "grafana"
 repository = local.helm_repository.grafana
 chart      = "grafana"
 version    = local.helm_repository.grafana_version
 namespace  = kubernetes_namespace.cluster_tools.0.id
 wait       = false

 set {
   name  = "grafana\\.ini.server.root_url"
   value = "%(protocol)s://%(domain)s:%(http_port)s/grafana" <------------------------ path
   type  = "string"
 }

I found this in their kubernetes terraform module.

  • You see they generated a host FQDN at some point and stored it in ingress_hosts variable. (i.e ="k8sapp.28e9459d.nip.io")
resource "kubernetes_ingress_v1" "grafana" {
 wait_for_load_balancer = true
 metadata {
   name        = "grafana"
   namespace   = kubernetes_namespace.cluster_tools.0.id
   annotations = local.ingress_nginx_annotations
 }
 spec {
   ingress_class_name = "nginx"
   rule {
     http {
       path {
         path      = "/grafana(/|$)(.*)"  <-------------path
         path_type = "Prefix"
         backend {
           service {
             name = "grafana"
             port {
               number = 80
             } }}}}
              }
      dynamic "rule" {
     for_each = local.ingress_hosts     <--------------the host FQDN k8sapp.28e9459d.nip.io
     content {
       host = rule.value
       http {
         path {
           path      = "/grafana(/|$)(.*)"
           path_type = "Prefix"
           backend {
             service {
               name = "grafana"
               port {
                 number = 80
               }  } } }  }  }  }
   tls {
     secret_name = "grafana-${var.ingress_cluster_issuer}-tls"
     hosts       = local.ingress_hosts     <---------------hotsname k8sapp.28e9459d.nip.io
   }
 }            
@brokedba commented on GitHub (Nov 30, 2024): > Thanks for reporting back. We can look at re-working the ingress in the template to only define the host if it's included as a value to help any future OCI users. What I noticed in other addon helm based installation in OCI is that there if the microservice is expecting a path i.e /webui the ingress can be created with a host matching it. ```yaml resource "helm_release" "grafana" { name = "grafana" repository = local.helm_repository.grafana chart = "grafana" version = local.helm_repository.grafana_version namespace = kubernetes_namespace.cluster_tools.0.id wait = false set { name = "grafana\\.ini.server.root_url" value = "%(protocol)s://%(domain)s:%(http_port)s/grafana" <------------------------ path type = "string" } ``` I found this in their kubernetes terraform module. - You see they generated a host FQDN at some point and stored it in `ingress_hosts` variable. (i.e =`"k8sapp.28e9459d.nip.io"`) ```yaml resource "kubernetes_ingress_v1" "grafana" { wait_for_load_balancer = true metadata { name = "grafana" namespace = kubernetes_namespace.cluster_tools.0.id annotations = local.ingress_nginx_annotations } spec { ingress_class_name = "nginx" rule { http { path { path = "/grafana(/|$)(.*)" <-------------path path_type = "Prefix" backend { service { name = "grafana" port { number = 80 } }}}} } dynamic "rule" { for_each = local.ingress_hosts <--------------the host FQDN k8sapp.28e9459d.nip.io content { host = rule.value http { path { path = "/grafana(/|$)(.*)" path_type = "Prefix" backend { service { name = "grafana" port { number = 80 } } } } } } } tls { secret_name = "grafana-${var.ingress_cluster_issuer}-tls" hosts = local.ingress_hosts <---------------hotsname k8sapp.28e9459d.nip.io } } ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: open-webui/helm-charts#31