Skip to main content

Self-Hosted LLM Behind Pomerium

This guide shows how to run a self-hosted LLM web interface (e.g., Open WebUI) and protect it behind Pomerium. Similar to the code-server guide, this setup applies enterprise-grade access controls to a local LLM, while passing user identity information through trusted headers so the upstream application knows who’s accessing it.

Why Use Open WebUI?

Open WebUI is a self-hosted interface for interacting with local or remote LLMs. Hosting it locally allows:

  • Private experimentation with different LLMs
  • Full control over data and configuration
  • Integration of custom features like retrieval augmentation, voice, or browsing

Why Pomerium?

By placing Open WebUI behind Pomerium, you can:

  • Authenticate users with your existing IdP (e.g., Google, GitHub, corporate SSO).
  • Enforce policy-based access using user attributes like email domain.
  • Pass identity headers (e.g., X-Pomerium-Claim-Email) to the upstream app, letting it personalize the experience without separate logins.

Pomerium injects trusted identity information, so Open WebUI can recognize authenticated users and skip its own password handling.

Overview

  1. Run Open WebUI in Docker.
  2. Configure Pomerium Zero to secure it.
  3. Access the LLM UI through a protected URL. Pomerium handles auth, passes user identity, and ensures only allowed users access the LLM.

Prerequisites

  • Pomerium Zero account
  • Docker and Docker Compose
  • A machine capable of running your chosen LLM backend

For GPU acceleration, follow Open WebUI’s CUDA instructions.

Configure Pomerium Zero

Create a Policy

Define who can access the LLM interface. For example, restrict access to your email domain:

  1. In the Zero Console, go to PoliciesNew Policy.
  2. Name it LLM Access.
  3. Add an allow condition: Domain equals example.com.

This ensures only authenticated users with example.com email addresses can access the route.

Create a Route

Map an external domain to the internal Open WebUI service. For example:

Screenshot of Pomerium route editing UI showing "LLM Access" route configuration

  1. In the Zero Console, go to RoutesNew Route.
  2. Name: LLM Access
  3. From: https://llm.your-domain.pomerium.app
  4. To: http://openwebui:8080
  5. Policies: Select LLM Access

Save the route. Now only authorized users can reach llm.your-domain.pomerium.app.

Enable Websockets

LLM UIs often use streaming responses:

Screenshot of Pomerium Timeouts configuration with Allow Websockets enabled

  • Under Timeouts, toggle Allow Websockets to On.

Preserve Host Header & Pass Identity

Enable these settings so Open WebUI receives the correct host header and identity claims:

Screenshot of Pomerium Headers configuration with Pass Identity Headers and Preserve Host Header enabled

  • Pass Identity Headers: On
  • Preserve Host Header: On

This ensures Pomerium forwards identity info like X-Pomerium-Claim-Email. In Settings, you can define how claims map to headers:

Screenshot of Pomerium cluster settings mapping X-Pomerium-Claim-Email to the user's email

With these settings, Open WebUI trusts the identity headers and can attribute actions to the authenticated user.

Example Docker Compose

Use placeholders for secrets and adjust WEBUI_URL to your external route. If you trust Pomerium’s headers, set WEBUI_AUTH=False in Open WebUI.

version: '3.9'
services:
pomerium:
image: pomerium/pomerium:v0.27.2
ports:
- 443:443
restart: always
environment:
POMERIUM_ZERO_TOKEN: '<YOUR_CLUSTER_TOKEN>'
XDG_CACHE_HOME: /var/cache
volumes:
- pomerium-cache:/var/cache
networks:
main:
aliases:
- authenticate.<YOUR_CLUSTER_SUBDOMAIN>.pomerium.app

openwebui:
image: ghcr.io/open-webui/open-webui:main
environment:
HOST: '0.0.0.0'
OLLAMA_HOST: '0.0.0.0'
WEBUI_URL: 'https://llm.your-domain.pomerium.app'
WEBUI_AUTH_TRUSTED_EMAIL_HEADER: 'X-Pomerium-Claim-Email'
WEBUI_AUTH: 'False'
ports:
- 3000:8080
volumes:
- open-webui-data:/app/backend/data
restart: always
networks:
main: {}

networks:
main:

volumes:
pomerium-cache:
open-webui-data:

Replace <YOUR_CLUSTER_TOKEN> and YOUR_CLUSTER_SUBDOMAIN. For GPU support, see Open WebUI docs.

Run and Access

docker compose up -d

Visit https://llm.your-domain.pomerium.app. After authenticating via your IdP, Pomerium routes you to Open WebUI with identity headers included.

Test the LLM

  • Load a model, prompt it, and interact.
  • Your identity is passed through; Open WebUI sees your user email. No extra passwords needed.
  • The entire session is protected behind Pomerium’s authentication and authorization.

Example of a Secured UI

Screenshot of Open WebUI protected by Pomerium, user authenticated as &quot;Bobby DeSimone&quot;

Next Steps

  • Refine policies: Add group-based rules or restrict certain endpoints.
  • Integrate different backends: Adjust OLLAMA_BASE_URL or OPENAI_API_KEY.
  • Add more routes behind Pomerium to scale your secure environment.

You’ve successfully secured a self-hosted LLM WebUI using Pomerium, with identity-aware access control and automatic user recognition upstream.