はじめに
今回は、SUSE AI Factory で提供されている、ブラウザからLLMとチャット形式で対話できるWebインターフェースのOpen WebUIの紹介をします。
本記事では最初にOpen WebUIの概要を説明し、その後、AirGap環境のRancherにOpen WebUIを構築する方法を解説します。
Open WebUIとは
Open WebUIは、LLMとチャット形式で対話するためのセルフホスト型のWebインターフェースです。
主な特徴は以下になります。
- ブラウザからGUI上でチャット画面を利用することが可能
- 適当なドキュメントを参照して回答させるRAGや文書作成のAIサポートなど、AIを利用した機能が豊富にある
- 外部のツールとの連携により機能の拡張が可能
- インターネット接続環境だけでなく、インターネット非接続環境でも動作するように設計されており、社外にデータを公開したくないといったセキュリティ要件がある場合でも導入できる
- 推論エンジンのOllamaおよびOpenAI互換APIをサポートしており、利用目的に合わせてモデルを切り替えて動作させることが可能
つまり、Open WebUIは、自分たちの要件に合わせて構築でき、多様なモデルをブラウザ画面上で使い分けられる、統合的なWebインターフェースです。詳細な機能については今後のブログで紹介します。
Open WebUIの設定方法
設定概要
今回利用するSUSE AIのHelm チャートでは、推論エンジンであるOllamaが Open WebUIとセットでパッケージ化されているため、まとめて同時に構築します。
Open WebUI構築の事前準備として以下の手順を実行します。
- Open WebUIのデータを保存するPostgreSQLの構築
- NFSディレクトリ上へのモデルデータの配置
- 利用するモデルはGemma4:12B, embeddinggemma:300mの2種類
- モデルデータを保存するNFSディレクトリと連携するPVの作成
その後、Open WebUI・Ollamaのインストールおよび管理者アカウントの作成まで行います。
本記事で構築するコンポーネントのバージョンは次のとおりです。
| コンポーネント名 | バージョン |
|---|---|
| PostgreSQL | 18.6-16.2 |
| Ollama | 0.32.14-11.78 |
| Open WebUI | 0.6.41-14.20 |
前提条件
基本的な前提条件は、過去の記事をご参照ください。
- SUSE RancherでのGPUノード設定方法解説 〜AirGap環境へのNVIDIA GPU Driver・GPU Operator導入〜
- SUSE Rancher PrimeでのSUSE AI Factory導入手順解説 〜AirGap環境におけるOperatorインストールと初期設定〜
上記に加えて、以下の条件が追加されます。
- 作業用端末にNFSを準備して、NFS Provisioner等でStorageClassとして利用できる状態になっていること
- SUSE AI Factoryがインストール済みであること
Open WebUI用のPostgreSQL構築
コンテナレジストリのプロジェクト作成
PostgreSQLのHelmチャートとコンテナイメージを配置するためのプロジェクトは以下のとおりです。
| プロジェクト名 | 用途 |
|---|---|
| postgresql-chart | PostgreSQLのHelmチャート配置先 |
| suse-ai | PostgreSQLのコンテナイメージ配置先 |
suse-aiは前回のブログで作成しているので、postgresql-chartのみ新規作成します。
コンテナレジストリにPostgreSQLのHelmチャート・コンテナイメージを登録
作業用端末で以下のコマンドを実行し、PostgreSQLのHelmチャートとコンテナイメージをコンテナレジストリへ登録します。
# PostgreSQLのHelmチャートをダウンロード
$ helm pull oci://dp.apps.rancher.io/charts/postgresql --version 0.8.0
# 出力例
Pulled: dp.apps.rancher.io/charts/postgresql:0.8.0
Digest: sha256:f7785fb03cf1b7924411366c07f215bb54324b974d9bf8c875f8b35b66ed2e7d
# Helmチャートをコンテナレジストリに登録
$ helm push postgresql-0.8.0.tgz oci://<コンテナレジストリのドメイン>/postgresql-chart --insecure-skip-tls-verify
# 出力例
Pushed: <コンテナレジストリのドメイン>/postgresql-chart/postgresql:0.8.0
Digest: sha256:83bca4535238e17dacef2cb36a080d8e9cdfb835711612f7442f28f108868a48
# PostgreSQLで使用するコンテナイメージをコンテナレジストリに登録
$ skopeo copy \
docker://dp.apps.rancher.io/containers/postgresql:18.6-16.2 \
docker://<コンテナレジストリのドメイン>/suse-ai/containers/postgresql:18.6-16.2
# 出力例
Getting image source signatures
Copying blob b98a90725c89 done |
Copying blob f9f0dbd5b8f1 skipped: already exists
Copying config 618df7c397 done |
Writing manifest to image destination
# PostgreSQLで使用するコンテナイメージをコンテナレジストリに登録
$ skopeo copy \
docker://dp.apps.rancher.io/containers/bci-micro:15.7-61.11 \
docker://<コンテナレジストリのドメイン>/suse-ai/containers/bci-micro:15.7-61.11
Rancher管理UIへのOCIリポジトリ登録
Rancher管理UIにログインし、「downstream」からDownstreamクラスターの管理画面に遷移します。


「Apps」→「Repositories」に移動します。

「Add Repository」から以下の設定値で「OCI Repository」の登録をします。
| 設定項目 | 設定値 |
|---|---|
| Target | OCI Repository |
| Name | 任意のリポジトリ名 |
| OCI Repository Host URL | oci://<コンテナレジストリのドメイン>/postgresql-chart |
| Authentication | Create an HTTP Basic Auth Secret |
| Username | <コンテナレジストリのユーザー名> |
| Password | <コンテナレジストリのパスワード> |
| Skip TLS Verifications | 有効化 |
PostgreSQLのインストール
作業用端末からkubectlでDownstreamクラスターに接続し、以下のコマンドでPostgreSQLのパスワードを設定したSecretを作成します。
# PostgreSQL用のNamespaceを作成
$ kubectl create ns postgresql
# 出力例
namespace/postgresql created
# PostgreSQL用のNamespaceにパスワードを設定したSecretを作成
$ kubectl create secret generic postgresql-secret \
--from-literal=postgresPassword="<任意の管理者パスワード>" \
--from-literal=password="<任意のDBユーザーパスワード>" \
--from-literal=replicationPassword="<任意のレプリケーションパスワード>" \
-n postgresql
# 出力例
secret/postgresql-secret created
Rancher管理UIのDownstreamクラスター管理画面から、「Apps」→「Charts」に移動し、「postgresql」のHelmチャートインストールページに移動します。


「Install this version」から以下の設定値でPostgreSQLをインストールします。
| 設定項目 | 設定値 |
|---|---|
| Namespace | postgresql |
| Name | postgresql |
| Edit YAML | 以下のvalues.yamlを参照 ※PVのStorageClassはNFSを指すようにします。 |
# values.yaml
# 認証情報および既存Secretの参照設定
auth:
database: "Open WebUI"
username: "suse_ai_user"
existingSecret: "postgresql-secret"
passwordKey: password
postgresPasswordKey: postgresPassword
postgresUsername: postgres
replicationPasswordKey: replicationPassword
replicationUsername: replication
# プライベートレジストリ上のコンテナイメージ指定
images:
postgresql:
registry: <コンテナレジストリのドメイン>
repository: suse-ai/containers/postgresql
tag: 18.6-16.2
volume-permissions:
registry: <コンテナレジストリのドメイン>
repository: suse-ai/containers/bci-micro
tag: 15.7-61.11
# 永続ボリューム(PV)の指定
persistence:
enabled: true
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: "<NFSのstorageClassName>"
作業用端末からkubectlでDownstreamクラスターに接続し、以下のコマンドでPostgreSQLのPodが起動していることを確認します。
$ kubectl get pod -n postgresql
# 出力例
NAME READY STATUS RESTARTS AGE
postgresql-0-1790918761-0 1/1 Running 0 57s
モデルデータの配置
作業用端末のNFSディレクトリ上にモデルデータ配置用ディレクトリを作成
作業用端末で以下のコマンドを実行し、モデルデータ配置用のディレクトリを作成します。
$ mkdir /nfs/ollama-models
$ sudo chmod 777 /nfs/ollama-models
モデルデータをダウンロード
作業用端末で以下のコマンドを実行し、前手順で作成したディレクトリにモデルデータをダウンロードします。
$ cd /nfs/ollama-models
# models_download.shのファイル内容をコピーする
$ vi models_download.sh
# モデルをダウンロードするスクリプトを実行
$ bash ./models_download.sh
# 出力例
==========================================
Processing: gemma4:12b
==========================================
Downloading manifest...
[DOWNLOADING] sha256-e5ca99f918964e7d5a912f974eae708ae59370883a5b182fc0660fe7adf3f0e4 ...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
...略
Download complete
# modelsディレクトリ配下にblobs・manifestsの2つのディレクトリが作成されていることを確認する
$ ls /nfs/ollama-models/models
# 出力例
blobs manifests
models_download.shは以下のmodels_download.shを参照してください。
通常はOllamaはインターネット上のOllama公式レジストリから直接モデルを取得します。しかし、AirGap環境では公式レジストリから直接モデルを取得できないので、このスクリプトを用いて、公式レジストリからモデルファイルを作業用端末のNFSディレクトリに直接ダウンロードします。そのNFSディレクトリをPV連携することで、間接的にAirGap環境のOllamaにモデルをデプロイすることが可能になります。
#!/bin/bash
# models_download.sh
set -e
# 対象モデルのリスト (形式 "リポジトリ名:タグ")
MODELS=(
"gemma4:12b"
"embeddinggemma:300m"
)
# 保存先ベースディレクトリの作成
mkdir -p ./models/blobs
for model in "${MODELS[@]}"; do
repo=$(echo "$model" | cut -d':' -f1)
tag=$(echo "$model" | cut -d':' -f2)
echo "=========================================="
echo "Processing: ${repo}:${tag}"
echo "=========================================="
# 1. 該当モデルの認証トークンを取得
TOKEN=$(curl -s "https://registry.ollama.ai/v2/token?service=registry.ollama.ai&scope=repository:library/${repo}:pull" | jq -r .token)
# 2. マニフェスト用ディレクトリの作成と取得
manifest_dir="./models/manifests/registry.ollama.ai/library/${repo}"
mkdir -p "$manifest_dir"
manifest_path="${manifest_dir}/${tag}"
echo "Downloading manifest..."
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"https://registry.ollama.ai/v2/library/${repo}/manifests/${tag}" \
-o "$manifest_path"
# 3. Blob (モデル重み・構成ファイル) のダウンロード
digests=$(jq -r '.config.digest, .layers[].digest' "$manifest_path")
for digest in $digests; do
filename=$(echo "$digest" | sed 's/:/-/')
blob_path="./models/blobs/$filename"
if [ -f "$blob_path" ]; then
echo " [SKIP] $filename (すでに存在します)"
else
echo " [DOWNLOADING] $filename ..."
curl -L -H "Authorization: Bearer $TOKEN" \
"https://registry.ollama.ai/v2/library/${repo}/blobs/${digest}" \
-o "$blob_path"
fi
done
done
echo ""
echo "Download complete"
Open WebUI・Ollamaの構築
PostgreSQL認証用のSecretを作成
作業用端末からkubectlでDownstreamクラスターに接続し、以下のコマンドでPostgreSQL認証用のSecretを作成します。
パスワードはPostgreSQL用のSecretを作成した際に設定した値と同じ設定値を入力する。
# Open WebUI用のNamespaceを作成
$ kubectl create ns open-webui-system
# 出力例
namespace/open-webui-system created
# Open WebUI用のNamespaceにPostgreSQL認証用のSecretを作成
$ kubectl create secret generic postgresql-secret \
--from-literal=password="<PostgreSQL用のSecretに設定したDBユーザーパスワード>" \
-n open-webui-system
# 出力例
secret/postgresql-secret created
Ollamaへのモデルデータ連携用PVを作成
作業用端末で作業用のディレクトリを作成します。
$ mkdir ollama
$ cd ollama
モデルデータを配置したディレクトリを指定したPV設定ファイルollama-model-pv.yamlを作成します。
# ollama-model-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: ollama-models-pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
nfs:
server: <作業用端末のIPアドレス>
path: "/nfs/ollama-models"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ollama-models-pvc
namespace: open-webui-system
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
storageClassName: ""
volumeName: ollama-models-pv
作業用端末からkubectlでDownstreamクラスターに接続し、以下のコマンドでPV・PVCを作成します。
$ kubectl apply -f ollama-model-pv.yaml
# 出力例
persistentvolume/ollama-models-pv created
persistentvolumeclaim/ollama-models-pvc created
Open WebUIのインストール
SUSE AI Factoryの管理UIから「Apps」→「Open WebUI」を選択します。

以下の設定値でOpen WebUIをインストールします。
| 設定項目 | 設定値 |
|---|---|
| Instance Name | open-webui |
| Namespace | open-webui-system |
| Chart Name | open-webui |
| Version | 8.19.1 |
| Deployment Type | Fleet Bundle |
| Select Target Cluster(s) | downstream |
| Configuration | 以下のopen-webui-values.yamlを参照 |
# open-webui-values.yaml
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
# control-plane ラベルが存在しないノードの優先度を上げる
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
replicaCount: 2 # レプリカ追加
image:
registry: <コンテナレジストリのドメイン>/suse-ai
repository: containers/open-webui
tag: 0.6.41-14.20
pullPolicy: IfNotPresent
ingress:
enabled: true
class: traefik
host: <Open WebUIのドメイン>
tls: false
persistence:
enabled: true
accessModes:
- ReadWriteMany
size: 2Gi
storageClass: <nfsのstrorageclassname>
extraEnvVars:
- name: WEBUI_SECRET_KEY
value: "<ランダムな値を設定>"
- name: DATABASE_TYPE
value: "postgres"
- name: DATABASE_HOST
value: "postgresql.postgresql.svc.cluster.local"
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_NAME
value: "Open WebUI"
- name: DATABASE_USER
value: "suse_ai_user"
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-secret
key: password
ollama:
enabled: true
fullnameOverride: open-webui-ollama
image:
registry: <コンテナレジストリのドメイン>/suse-ai
repository: containers/ollama
tag: "0.32.14-11.78"
ollama:
gpu:
enabled: true
type: "nvidia"
number: 1
ingress:
enabled: true
className: traefik
hosts:
- host: <Ollamaのドメイン>
paths:
- path: /
pathType: Prefix
extraEnv:
- name: OLLAMA_MAX_LOADED_MODELS # モデルデータの最大同時ロード数
value: "2"
- name: OLLAMA_NUM_PARALLEL # 4リクエストまで同時処理できるようにする
value: "4"
persistentVolume:
enabled: true
existingClaim: "ollama-models-pvc" # モデルデータ配置用PVを割り当て
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
nodeSelector:
accelerator: nvidia-gpu
tolerations:
- key: "nvidia.com/gpu"
operator: "Equal"
value: "dedicated"
effect: "NoSchedule"
websocket:
enabled: true
manager: redis
url: redis://open-webui-redis:6379/0
redis:
name: open-webui-redis
image:
registry: <コンテナレジストリのドメイン>/suse-ai
repository: containers/redis
tag: 8.4.0-2.1
pullPolicy: IfNotPresent
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
作業用端末からkubectlでDownstreamクラスターに接続し、以下のコマンドでOpen WebUI・OllamaのPodが起動していることを確認します。
$ kubectl get pod -n open-webui-system
# 出力例
NAME READY STATUS RESTARTS AGE
open-webui-0 1/1 Running 0 39m
open-webui-1 1/1 Running 0 39m
open-webui-ollama-7f7847cd5f-vtj68 1/1 Running 0 39m
open-webui-pipelines-754467f8b8-dgc76 1/1 Running 0 39m
open-webui-redis-774866f675-pdn45 1/1 Running 0 39m
Open WebUIのアカウント作成
ブラウザからOpen WebUIにアクセスし、アカウントの作成を行います。
※初回登録のアカウントが管理者アカウントとなります。

アカウント作成後、Open WebUIのチャット画面にログインできることを確認します。

おわりに
本記事ではOpen WebUIについての概要とAirGap環境での設定・構築方法について紹介しました。これでCLIではなく、GUIで便利にAIを利用することが可能になります。
次回はSUSE AI Factory で提供されている推論エンジンの1つであるOllamaの仕組みと特徴を解説したいと思います。
参考


