4 Commits

Author SHA1 Message Date
f4cf55b3c8 Open WebUI OIDC & proxy fixes + Ollama preload + async-safe pull
- svc-ai-ollama:
  - Add preload_models (llama3, mistral, nomic-embed-text)
  - Pre-pull task: loop_var=model, async-safe changed_when/failed_when

- sys-svc-proxy (OpenResty):
  - Forward Authorization header
  - Ensure proxy_pass_request_headers on

- web-app-openwebui:
  - ADMIN_EMAIL from users.administrator.email
  - Request RBAC group scope in OAUTH_SCOPES

Ref: ChatGPT support (2025-09-23) — https://chatgpt.com/share/68d20588-2584-800f-aed4-26ce710c69c4
2025-09-23 04:27:46 +02:00
1b91ddeac2 Optimized flowise 2025-09-23 03:03:11 +02:00
b638d00d73 Removed unneccessary MINIO_OIDC_POLICY_NAME_SAFE 2025-09-23 03:02:40 +02:00
75c36a1d71 web-app-minio: manage OIDC policy via containerized mc and fix policy JSON
- Use dockerized mc with MC_HOST_minio (stateless), no temp files/dirs
- Create only RAW policy name with slash to match Keycloak claim
- Split policy: s3:* on S3 ARNs; admin:* on Resource "*"
- Add mc vars (image, MC_HOST components) to vars/main.yml
- Remove unused Ollama dependency block from tasks

Refs: ChatGPT conversation → https://chatgpt.com/share/68d1eab9-a35c-800f-aa81-76fb2101bd93
2025-09-23 02:33:35 +02:00
12 changed files with 81 additions and 37 deletions

View File

@@ -11,4 +11,8 @@ docker:
port: 11434
volumes:
models: "ollama_models"
network: "ollama"
network: "ollama"
preload_models:
- "llama3:latest"
- "mistral:latest"
- "nomic-embed-text:latest"

View File

@@ -16,4 +16,23 @@
vars:
docker_compose_flush_handlers: true
- name: Pre-pull Ollama models
vars:
_cmd: "docker exec -i {{ OLLAMA_CONTAINER }} ollama pull {{ model }}"
shell: "{{ _cmd }}"
register: pull_result
loop: "{{ OLLAMA_PRELOAD_MODELS }}"
loop_control:
loop_var: model
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
changed_when: >
(not (ASYNC_ENABLED | bool)) and (
'downloaded' in (pull_result.stdout | default('')) or
'pulling manifest' in (pull_result.stdout | default(''))
)
failed_when: >
(pull_result.rc | default(0)) != 0 and
('up to date' not in (pull_result.stdout | default('')))
- include_tasks: utils/run_once.yml

View File

@@ -12,3 +12,5 @@ OLLAMA_CONTAINER: "{{ applications | get_app_conf(application_id,
OLLAMA_PORT: "{{ applications | get_app_conf(application_id, 'docker.services.ollama.port') }}"
OLLAMA_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.models') }}"
OLLAMA_NETWORK: "{{ applications | get_app_conf(application_id, 'docker.network') }}"
OLLAMA_PRELOAD_MODELS: "{{ applications | get_app_conf(application_id, 'preload_models') }}"

View File

@@ -10,10 +10,12 @@ location {{location}}
# headers
proxy_set_header Host $host;
proxy_set_header Authorization $http_authorization;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port {{ WEB_PORT }};
proxy_pass_request_headers on;
{% include 'roles/sys-svc-proxy/templates/headers/content_security_policy.conf.j2' %}

View File

@@ -8,8 +8,8 @@ features:
local_ai: true
server:
domains:
canonical:
flowise: "flowise.ai.{{ PRIMARY_DOMAIN }}"
canonical:
- "flow.ai.{{ PRIMARY_DOMAIN }}"
aliases: []
csp:
flags: {}
@@ -40,7 +40,7 @@ docker:
flowise:
backup:
no_stop_required: true
image: flowiseai/flowise:latest
image: flowiseai/flowise
version: latest
name: flowise
redis:

View File

@@ -23,9 +23,6 @@
- name: "flush handlers of docker compose"
meta: flush_handlers
- name: "Include role sys-stk-front-proxy for each UI domain"
- name: "Include role sys-stk-front-proxy for '{{ application_id }}'"
include_role:
name: sys-stk-front-proxy
vars:
domain: "{{ item.domain }}"
http_port: "{{ item.http_port }}"

View File

@@ -3,8 +3,6 @@
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: {{ FLOWISE_LITELLM_IMAGE }}:{{ FLOWISE_LITELLM_VERSION }}
container_name: {{ FLOWISE_LITELLM_CONTAINER }}
depends_on:
- ollama
expose:
- {{ FLOWISE_LITELLM_PORT }}
volumes:

View File

@@ -1,5 +1,7 @@
# General
application_id: "web-app-flowise"
application_id: "web-app-flowise"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
# Flowise
# https://flowiseai.com/

View File

@@ -1,20 +1,11 @@
---
- name: "Install Ollama Dependency"
include_role:
name: svc-ai-ollama
vars:
flush_handlers: true
when:
- run_once_svc_ai_ollama is not defined
- OLLAMA_LOCAL_ENABLED | bool
- name: "load docker and db for {{ application_id }}"
include_role:
name: sys-stk-back-stateless
vars:
docker_compose_flush_handlers: true
- name: "Include role sys-stk-front-proxy for each UI domain"
- name: "Include role sys-stk-front-proxy for '{{ application_id }}'"
include_role:
name: sys-stk-front-proxy
vars:
@@ -25,16 +16,32 @@
label: "{{ item.domain }} -> {{ item.http_port }}"
- block:
- name: "Render MinIO policy into variable"
set_fact:
minio_policy_content: "{{ lookup('template', 'policy.json.j2') }}"
- name: "Check policy (RAW with slash) exists"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
shell: >
docker run --rm
-e MC_HOST_minio={{ MINIO_MC_HOST_ENV | quote }}
{{ MINIO_MC_IMAGE }}
admin policy info minio {{ MINIO_OIDC_POLICY_NAME | quote }}
register: mc_policy_info_raw
failed_when: false
changed_when: false
- name: "Apply MinIO policy {{ MINIO_OIDC_POLICY_NAME }}"
- name: "Create policy (RAW with slash) if missing"
shell: |
set -euo pipefail
mc alias set minio {{ MINIO_API_URL }} {{ users.administrator.username }} {{ users.administrator.password }}
mc admin policy create minio {{ MINIO_OIDC_POLICY_NAME }} /dev/stdin || true
args:
executable: /bin/bash
stdin: "{{ minio_policy_content }}"
printf '%s' '{{ (MINIO_OIDC_POLICY_CONTENT | from_yaml | to_json) | b64encode }}' \
| base64 -d \
| docker run --rm -i \
-e MC_HOST_minio={{ MINIO_MC_HOST_ENV | quote }} \
{{ MINIO_MC_IMAGE }} \
admin policy create minio {{ MINIO_OIDC_POLICY_NAME | quote }} /dev/stdin
args: { executable: /bin/bash }
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
when:
- mc_policy_info_raw.rc != 0
when: MINIO_OIDC_ENABLED | bool

View File

@@ -3,14 +3,16 @@
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"admin:*"
],
"Action": ["s3:*"],
"Resource": [
"arn:aws:s3:::*",
"arn:minio:admin:::*"
"arn:aws:s3:::*/*"
]
},
{
"Effect": "Allow",
"Action": ["admin:*"],
"Resource": ["*"]
}
]
}

View File

@@ -24,9 +24,20 @@ MINIO_CONSOLE_URL: "{{ domains | get_url(application_id, WEB_PROTOC
MINIO_CONSOLE_PORT_INTERNAL: 9001
MINIO_CONSOLE_PORT_PUBLIC: "{{ ports.localhost.http[application_id ~ '_console'] }}"
## MC
MINIO_MC_IMAGE: "quay.io/minio/mc:latest"
MINIO_MC_INSECURE: false # set to true if you use self-signed TLS
MINIO_MC_SCHEME: "{{ 'https' if (MINIO_API_URL is match('^https://')) else 'http' }}"
MINIO_MC_HOST_ONLY: "{{ MINIO_API_URL | regex_replace('^https?://', '') }}"
MINIO_MC_USER: "{{ users.administrator.username | urlencode }}"
MINIO_MC_PASS: "{{ users.administrator.password | urlencode }}"
MINIO_MC_INSECURE_SUFFIX: "{{ '?insecure=true' if (MINIO_MC_INSECURE | bool) else '' }}"
MINIO_MC_HOST_ENV: "{{ MINIO_MC_SCHEME }}://{{ MINIO_MC_USER }}:{{ MINIO_MC_PASS }}@{{ MINIO_MC_HOST_ONLY }}{{ MINIO_MC_INSECURE_SUFFIX }}"
## OIDC
MINIO_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
MINIO_OIDC_POLICY_NAME: "{{ [ RBAC.GROUP.NAME, application_id ~ '-administrator' ] | path_join }}"
MINIO_OIDC_POLICY_CONTENT: "{{ lookup('template', 'policy.json.j2') }}"
MINIO_FRONT_PROXY_MATRIX: >-
{{

View File

@@ -14,7 +14,7 @@ ENABLE_PERSISTENT_CONFIG=false
# Use this to automatically assign the first admin in a fresh installation.
# The specified email will be promoted to ADMIN on first login.
# After initial setup you can remove this block and manage admins via the UI.
ADMIN_EMAIL=users.administrator.email
ADMIN_EMAIL={{ users.administrator.email }}
# If enabled, the pending-activation page will display the admins email address
# so new users know who to contact for access.
@@ -42,7 +42,7 @@ OPENID_REDIRECT_URI={{ OPENWEBUI_OIDC_REDIRECT_URL }}
OAUTH_PROVIDER_NAME={{ OIDC.BUTTON_TEXT }}
# Scopes to request (openid is required; email/profile recommended)
OAUTH_SCOPES=openid email profile
OAUTH_SCOPES=openid email profile {{ RBAC.GROUP.CLAIM }}
# =========================
# Optional: Role Management