diff --git a/.env.example b/.env.example index 28751cd..9981c6c 100644 --- a/.env.example +++ b/.env.example @@ -178,6 +178,7 @@ WEBUI_SECRET_KEY=changeme-openwebui-dev-secret AI_GATEWAY_API_KEY=ulti-gateway # OpenWebUI embed : modèles ultid visibles sans entrée DB par modèle BYPASS_MODEL_ACCESS_CONTROL=true +WEBUI_NAME=UltiAI AI_ASSISTANT_PUBLIC_PATH=/ai ULTIMAIL_MCP_URL=http://ultimail-mcp:3100 # OpenWebUI utilise POSTGRES_USER/POSTGRES_PASSWORD (base openwebui créée dans init-db.sh) diff --git a/deploy/nginx/default.conf.template b/deploy/nginx/default.conf.template index b81b241..908c9e0 100644 --- a/deploy/nginx/default.conf.template +++ b/deploy/nginx/default.conf.template @@ -383,6 +383,11 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; + proxy_set_header Accept-Encoding ""; + sub_filter_once off; + sub_filter_types application/json text/plain; + sub_filter 'UltiAI (Open WebUI)' 'UltiAI'; + sub_filter 'Open WebUI' 'UltiAI'; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } @@ -643,6 +648,20 @@ server { # SvelteKit base path — without this, /ai/ routes 404 (base "" expects site root) sub_filter 'base: ""' 'base: "/ai"'; sub_filter "base: ''" 'base: "/ai"'; + # In-app links that escape to site root (e.g. "Nouvelle conversation" → /) + sub_filter 'href="/"' 'href="/ai/"'; + sub_filter "href='/'" "href='/ai/'"; + sub_filter 'href="/notes' 'href="/ai/notes'; + sub_filter 'href="/workspace' 'href="/ai/workspace'; + sub_filter 'href="/home' 'href="/ai/home'; + sub_filter 'href="/c/' 'href="/ai/c/'; + sub_filter 'href="/automations' 'href="/ai/automations'; + sub_filter 'href="/calendar' 'href="/ai/calendar'; + sub_filter 'href="/channels' 'href="/ai/channels'; + sub_filter 'href="/playground' 'href="/ai/playground'; + # UltiAI branding (WEBUI_NAME env still appends " (Open WebUI)" in backend) + sub_filter 'UltiAI (Open WebUI)' 'UltiAI'; + sub_filter 'Open WebUI' 'UltiAI'; } location = /ai { @@ -692,6 +711,10 @@ server { sub_filter_types application/javascript text/javascript; sub_filter '"/api/' '"/ai/api/'; sub_filter "'/api/" "'/ai/api/"; + sub_filter 'href="/"' 'href="/ai/"'; + sub_filter "href='/'" "href='/ai/'"; + sub_filter 'Open WebUI' 'UltiAI'; + sub_filter 'UltiAI (Open WebUI)' 'UltiAI'; } location ^~ /_app/ { @@ -718,6 +741,10 @@ server { sub_filter_types application/javascript text/javascript application/json; sub_filter '"/api/' '"/ai/api/'; sub_filter "'/api/" "'/ai/api/"; + sub_filter 'href="/"' 'href="/ai/"'; + sub_filter "href='/'" "href='/ai/'"; + sub_filter 'Open WebUI' 'UltiAI'; + sub_filter 'UltiAI (Open WebUI)' 'UltiAI'; } location = /manifest.json { @@ -1002,6 +1029,12 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } + # OpenWebUI SPA routes without /ai prefix (client nav + hard reload in UltiAI iframe). + # Do not include "auth" — Ultimail OIDC uses /auth/application/o/… (Authentik). + location ~ ^/(notes|workspace|c|home|automations|calendar|channels|playground|watch|s|error)(/|$) { + return 302 /ai$uri$is_args$args; + } + location / { default_type text/plain; return 404 "Not found\n"; diff --git a/deploy/openwebui/docker-compose.openwebui.yml b/deploy/openwebui/docker-compose.openwebui.yml index 967f3a2..469062c 100644 --- a/deploy/openwebui/docker-compose.openwebui.yml +++ b/deploy/openwebui/docker-compose.openwebui.yml @@ -11,6 +11,7 @@ services: ENABLE_PERSISTENT_CONFIG: "false" ENABLE_DIRECT_CONNECTIONS: "false" BYPASS_MODEL_ACCESS_CONTROL: "true" + WEBUI_NAME: UltiAI OPENAI_API_BASE_URL: http://ultid:8080/api/v1/ai OPENAI_API_KEY: ${AI_GATEWAY_API_KEY:-ulti-gateway} WEBUI_URL: http://${DOMAIN:-localhost}/ai @@ -20,6 +21,9 @@ services: volumes: - openwebui_data:/app/backend/data - ../services/openwebui/pipelines:/app/pipelines/custom:ro + - ../services/openwebui/static/logo.png:/app/backend/open_webui/static/logo.png:ro + - ../services/openwebui/static/favicon.png:/app/backend/open_webui/static/favicon.png:ro + - ../services/openwebui/static/custom.css:/app/backend/open_webui/static/custom.css:ro networks: - ulti-net depends_on: diff --git a/services/openwebui/static/custom.css b/services/openwebui/static/custom.css new file mode 100644 index 0000000..731a44a --- /dev/null +++ b/services/openwebui/static/custom.css @@ -0,0 +1,4 @@ +/* UltiAI branding overrides (OpenWebUI custom.css hook) */ +:root { + --ultiai-brand: #1a73e8; +} diff --git a/services/openwebui/static/favicon.png b/services/openwebui/static/favicon.png new file mode 100644 index 0000000..50a37ac Binary files /dev/null and b/services/openwebui/static/favicon.png differ diff --git a/services/openwebui/static/logo.png b/services/openwebui/static/logo.png new file mode 100644 index 0000000..50a37ac Binary files /dev/null and b/services/openwebui/static/logo.png differ diff --git a/services/openwebui/static/ultiai-mark.svg b/services/openwebui/static/ultiai-mark.svg new file mode 100644 index 0000000..ad6e169 --- /dev/null +++ b/services/openwebui/static/ultiai-mark.svg @@ -0,0 +1,15 @@ +