> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-webui/open-webui/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes Deployment

> Deploy Open WebUI on Kubernetes

Deploy Open WebUI on Kubernetes using kubectl, Kustomize, or Helm charts for production-ready, scalable deployments.

## Prerequisites

* Kubernetes cluster (1.19+)
* kubectl configured to communicate with your cluster
* Persistent volume provisioner (for data persistence)
* Optional: Helm 3.x for Helm-based deployment

## Quick Start with Kubectl

### Basic Deployment

Create a deployment manifest `open-webui-deployment.yaml`:

```yaml open-webui-deployment.yaml theme={null}
apiVersion: v1
kind: Namespace
metadata:
  name: open-webui
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: open-webui-pvc
  namespace: open-webui
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: open-webui
  namespace: open-webui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: open-webui
  template:
    metadata:
      labels:
        app: open-webui
    spec:
      containers:
      - name: open-webui
        image: ghcr.io/open-webui/open-webui:main
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: OLLAMA_BASE_URL
          value: "http://ollama:11434"
        - name: WEBUI_SECRET_KEY
          valueFrom:
            secretKeyRef:
              name: open-webui-secret
              key: secret-key
        volumeMounts:
        - name: data
          mountPath: /app/backend/data
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "2000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: open-webui-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: open-webui
  namespace: open-webui
spec:
  type: ClusterIP
  selector:
    app: open-webui
  ports:
  - port: 80
    targetPort: 8080
    name: http
---
apiVersion: v1
kind: Secret
metadata:
  name: open-webui-secret
  namespace: open-webui
type: Opaque
stringData:
  secret-key: "your-secret-key-here"
```

Deploy:

```bash theme={null}
kubectl apply -f open-webui-deployment.yaml
```

### Expose with Ingress

Create an Ingress resource:

```yaml ingress.yaml theme={null}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: open-webui
  namespace: open-webui
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
  ingressClassName: nginx
  rules:
  - host: open-webui.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: open-webui
            port:
              number: 80
  tls:
  - hosts:
    - open-webui.example.com
    secretName: open-webui-tls
```

Apply:

```bash theme={null}
kubectl apply -f ingress.yaml
```

## Deploying with Ollama

### Combined Deployment

Deploy both Open WebUI and Ollama in the same namespace:

```yaml ollama-deployment.yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ollama-pvc
  namespace: open-webui
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ollama
  namespace: open-webui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ollama
  template:
    metadata:
      labels:
        app: ollama
    spec:
      containers:
      - name: ollama
        image: ollama/ollama:latest
        ports:
        - containerPort: 11434
          name: http
        volumeMounts:
        - name: ollama-data
          mountPath: /root/.ollama
        resources:
          requests:
            memory: "4Gi"
            cpu: "2000m"
          limits:
            memory: "16Gi"
            cpu: "8000m"
      volumes:
      - name: ollama-data
        persistentVolumeClaim:
          claimName: ollama-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: ollama
  namespace: open-webui
spec:
  type: ClusterIP
  selector:
    app: ollama
  ports:
  - port: 11434
    targetPort: 11434
    name: http
```

Apply:

```bash theme={null}
kubectl apply -f ollama-deployment.yaml
```

### GPU Support

For GPU support, add node selectors and resource limits:

```yaml theme={null}
spec:
  template:
    spec:
      nodeSelector:
        nvidia.com/gpu: "true"
      containers:
      - name: ollama
        resources:
          limits:
            nvidia.com/gpu: 1
```

## Horizontal Scaling

For multi-replica deployments, configure Redis for session management:

<Steps>
  <Step title="Deploy Redis">
    ```yaml redis-deployment.yaml theme={null}
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis
      namespace: open-webui
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
        spec:
          containers:
          - name: redis
            image: redis:7-alpine
            ports:
            - containerPort: 6379
            resources:
              requests:
                memory: "256Mi"
                cpu: "250m"
              limits:
                memory: "512Mi"
                cpu: "500m"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
      namespace: open-webui
    spec:
      type: ClusterIP
      selector:
        app: redis
      ports:
      - port: 6379
        targetPort: 6379
    ```
  </Step>

  <Step title="Configure Open WebUI for Redis">
    Update the Open WebUI deployment with Redis configuration:

    ```yaml theme={null}
    env:
    - name: REDIS_URL
      value: "redis://redis:6379"
    - name: WEBSOCKET_MANAGER
      value: "redis"
    - name: WEBSOCKET_REDIS_URL
      value: "redis://redis:6379"
    ```
  </Step>

  <Step title="Scale Replicas">
    ```bash theme={null}
    kubectl scale deployment/open-webui -n open-webui --replicas=3
    ```
  </Step>
</Steps>

## Database Configuration

### PostgreSQL Backend

For production deployments, use PostgreSQL instead of SQLite:

```yaml postgres-deployment.yaml theme={null}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
  namespace: open-webui
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: open-webui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:16-alpine
        env:
        - name: POSTGRES_DB
          value: "openwebui"
        - name: POSTGRES_USER
          value: "openwebui"
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-secret
              key: password
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: postgres-data
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: open-webui
spec:
  type: ClusterIP
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432
---
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
  namespace: open-webui
type: Opaque
stringData:
  password: "your-secure-password"
```

Update Open WebUI deployment:

```yaml theme={null}
env:
- name: DATABASE_URL
  value: "postgresql://openwebui:your-secure-password@postgres:5432/openwebui"
```

## ConfigMap for Environment Variables

Manage environment variables with ConfigMaps:

```yaml configmap.yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: open-webui-config
  namespace: open-webui
data:
  OLLAMA_BASE_URL: "http://ollama:11434"
  OPENAI_API_BASE_URL: ""
  WEBUI_NAME: "Open WebUI"
  ENV: "prod"
  ENABLE_SIGNUP: "true"
  DEFAULT_USER_ROLE: "pending"
```

Reference in deployment:

```yaml theme={null}
envFrom:
- configMapRef:
    name: open-webui-config
```

## Monitoring and Observability

### Prometheus Metrics

Enable OpenTelemetry metrics:

```yaml theme={null}
env:
- name: ENABLE_OTEL
  value: "true"
- name: ENABLE_OTEL_METRICS
  value: "true"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
  value: "http://otel-collector:4317"
- name: OTEL_SERVICE_NAME
  value: "open-webui"
```

## Using Helm (Community Charts)

While there isn't an official Helm chart, you can create your own or use community charts.

Basic Helm values structure:

```yaml values.yaml theme={null}
image:
  repository: ghcr.io/open-webui/open-webui
  tag: main
  pullPolicy: IfNotPresent

replicaCount: 1

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: open-webui.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: open-webui-tls
      hosts:
        - open-webui.example.com

persistence:
  enabled: true
  size: 10Gi
  storageClass: ""

env:
  OLLAMA_BASE_URL: "http://ollama:11434"
  WEBUI_NAME: "Open WebUI"

resources:
  requests:
    memory: 512Mi
    cpu: 500m
  limits:
    memory: 2Gi
    cpu: 2000m

redis:
  enabled: false
  url: ""

postgresql:
  enabled: false
  url: ""
```

## Security Best Practices

<Steps>
  <Step title="Use Secrets">
    Store sensitive data in Kubernetes Secrets, not ConfigMaps:

    ```bash theme={null}
    kubectl create secret generic open-webui-secret \
      --from-literal=secret-key=$(openssl rand -base64 32) \
      --from-literal=openai-api-key=your-key \
      -n open-webui
    ```
  </Step>

  <Step title="Network Policies">
    Restrict network access between pods:

    ```yaml networkpolicy.yaml theme={null}
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: open-webui-policy
      namespace: open-webui
    spec:
      podSelector:
        matchLabels:
          app: open-webui
      policyTypes:
      - Ingress
      - Egress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
        ports:
        - protocol: TCP
          port: 8080
      egress:
      - to:
        - podSelector:
            matchLabels:
              app: ollama
        ports:
        - protocol: TCP
          port: 11434
    ```
  </Step>

  <Step title="Pod Security Standards">
    Apply pod security standards:

    ```yaml theme={null}
    securityContext:
      runAsNonRoot: true
      runAsUser: 1000
      fsGroup: 1000
      seccompProfile:
        type: RuntimeDefault
    containers:
    - name: open-webui
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop:
          - ALL
        readOnlyRootFilesystem: false
    ```
  </Step>
</Steps>

## Troubleshooting

### Check Pod Status

```bash theme={null}
kubectl get pods -n open-webui
kubectl describe pod <pod-name> -n open-webui
```

### View Logs

```bash theme={null}
kubectl logs -f deployment/open-webui -n open-webui
```

### Check PVC Status

```bash theme={null}
kubectl get pvc -n open-webui
```

### Shell into Container

```bash theme={null}
kubectl exec -it deployment/open-webui -n open-webui -- /bin/bash
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Environment Variables" icon="gear" href="/deployment/environment-variables">
    Configure Open WebUI settings
  </Card>

  <Card title="Updating" icon="arrow-up" href="/deployment/updating">
    Update your Kubernetes deployment
  </Card>

  <Card title="Docker Deployment" icon="docker" href="/deployment/docker">
    Alternative Docker deployment
  </Card>

  <Card title="Reverse Proxy" icon="server" href="/deployment/reverse-proxy">
    Configure ingress and reverse proxy
  </Card>
</CardGroup>
