Add project and deployment instruction (docs/DEPLOYMENT.md)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ars
2026-02-19 18:12:09 +00:00
commit 53c572ef46
94 changed files with 9200 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
#!/bin/bash
# Скрипт для постоянной замены логотипов через volume монтирование
# Этот скрипт копирует файлы в volume, который сохраняется между перезапусками
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== Применение логотипов (постоянное решение) ==="
# Проверка наличия контейнера
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Поиск существующих favicon и logo файлов..."
# Находим все существующие favicon и logo файлы
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" -o -name "favicon-96x96.png" \) 2>/dev/null | head -20)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | head -20)
echo " Найдено favicon файлов: $(echo "$EXISTING_FAVICONS" | grep -v '^$' | wc -l)"
echo " Найдено logo файлов: $(echo "$EXISTING_LOGOS" | grep -v '^$' | wc -l)"
# Заменяем все найденные favicon файлы
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "2. Замена всех favicon файлов на favicon.png..."
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ]; then
echo "$favicon_file"
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
# Также создаем .ico версию в той же директории
favicon_dir=$(dirname "$favicon_file")
favicon_name=$(basename "$favicon_file" | sed 's/\.[^.]*$//')
if [ "$favicon_name" != "favicon" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
fi
# Заменяем все найденные logo файлы
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "3. Замена всех logo файлов на logo.png..."
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ]; then
echo "$logo_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
# Также создаем .svg версию
logo_dir=$(dirname "$logo_file")
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_dir}/logo.svg" 2>/dev/null || true
fi
done
fi
echo ""
echo "4. Перезапуск контейнера для применения изменений..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Не удалось перезапустить контейнер автоматически."
echo "Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== Готово! ==="
echo ""
echo "ВАЖНО: Логотипы применены, но они могут вернуться после перезапуска контейнера."
echo ""
echo "Для ПОСТОЯННОГО решения используйте Admin Panel Open WebUI:"
echo " 1. Откройте https://odo.iieasy.ru или http://localhost:3001"
echo " 2. Войдите как администратор"
echo " 3. Settings → Appearance → Logo"
echo " 4. Загрузите logo.png и favicon.png из папки media/"
echo " 5. Сохраните - настройки сохранятся в базе данных"
echo ""
echo "Или запустите этот скрипт после каждого перезапуска контейнера."

100
scripts/check_gpu.sh Executable file
View File

@@ -0,0 +1,100 @@
#!/bin/bash
# Скрипт для проверки подключения GPU в Docker контейнере Ollama
set -e
CONTAINER_NAME="ollama"
echo "=== Проверка GPU в Docker контейнере ==="
echo ""
# Определяем команду docker
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
echo "1. Проверка конфигурации в docker-compose.yml..."
if grep -q "driver: nvidia" docker-compose.yml 2>/dev/null; then
echo " ✓ GPU настроен в docker-compose.yml"
echo " Конфигурация:"
grep -A 5 "driver: nvidia" docker-compose.yml | head -6
else
echo " ✗ GPU не настроен в docker-compose.yml"
fi
echo ""
echo "2. Проверка конфигурации контейнера..."
GPU_CONFIG=$($DOCKER_CMD inspect $CONTAINER_NAME 2>/dev/null | grep -i "nvidia\|gpu" | head -5)
if [ -n "$GPU_CONFIG" ]; then
echo " ✓ Найдена конфигурация GPU:"
echo "$GPU_CONFIG"
else
echo " ⚠ Конфигурация GPU не найдена в inspect"
fi
echo ""
echo "3. Проверка доступности nvidia-smi в контейнере..."
if $DOCKER_CMD exec $CONTAINER_NAME which nvidia-smi >/dev/null 2>&1; then
echo " ✓ nvidia-smi доступен"
echo ""
echo " Вывод nvidia-smi:"
$DOCKER_CMD exec $CONTAINER_NAME nvidia-smi 2>&1 | head -15 || echo " ⚠ nvidia-smi не может выполниться"
else
echo " ✗ nvidia-smi не найден в контейнере"
echo " Возможно, контейнер не имеет доступа к GPU"
fi
echo ""
echo "4. Проверка переменных окружения NVIDIA..."
NVIDIA_ENV=$($DOCKER_CMD exec $CONTAINER_NAME env | grep -i nvidia)
if [ -n "$NVIDIA_ENV" ]; then
echo " ✓ Переменные NVIDIA найдены:"
echo "$NVIDIA_ENV"
else
echo " ⚠ Переменные NVIDIA не найдены"
fi
echo ""
echo "5. Проверка логов Ollama на использование GPU..."
RECENT_LOGS=$($DOCKER_CMD logs $CONTAINER_NAME --tail 50 2>&1)
if echo "$RECENT_LOGS" | grep -qi "gpu\|cuda\|nvidia"; then
echo " ✓ Найдены упоминания GPU в логах:"
echo "$RECENT_LOGS" | grep -i "gpu\|cuda\|nvidia" | tail -5
else
echo " ⚠ Нет упоминаний GPU в последних логах"
fi
echo ""
echo "6. Проверка на хосте..."
if command -v nvidia-smi >/dev/null 2>&1; then
echo " GPU на хосте:"
nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader 2>/dev/null || echo " ⚠ Не удалось получить информацию о GPU"
else
echo " ⚠ nvidia-smi не найден на хосте"
fi
echo ""
echo "=== Резюме ==="
echo ""
if $DOCKER_CMD exec $CONTAINER_NAME nvidia-smi >/dev/null 2>&1; then
echo "✓ GPU подключен и доступен в контейнере"
echo ""
echo "Для детальной информации выполните:"
echo " sudo docker exec ollama nvidia-smi"
else
echo "✗ GPU не доступен в контейнере"
echo ""
echo "Возможные причины:"
echo " 1. Docker не имеет доступа к GPU (нужен nvidia-docker2 или nvidia-container-toolkit)"
echo " 2. Контейнер не был перезапущен после изменения docker-compose.yml"
echo " 3. Драйверы NVIDIA не установлены на хосте"
echo ""
echo "Решение:"
echo " 1. Установите nvidia-container-toolkit:"
echo " sudo apt-get install -y nvidia-container-toolkit"
echo " sudo systemctl restart docker"
echo ""
echo " 2. Перезапустите контейнер:"
echo " docker compose restart ollama"
fi

85
scripts/check_image_transfer.sh Executable file
View File

@@ -0,0 +1,85 @@
#!/bin/bash
# Скрипт для проверки передачи изображений из Open WebUI в Ollama
set -e
echo "=== Проверка передачи изображений Open WebUI → Ollama ==="
echo ""
# Определяем команду docker
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
echo "1. Проверка переменной OLLAMA_BASE_URL в контейнере..."
OLLAMA_URL=$($DOCKER_CMD exec open-webui env | grep -i "OLLAMA_BASE_URL" | cut -d= -f2)
if [ -z "$OLLAMA_URL" ]; then
echo " ✗ Переменная OLLAMA_BASE_URL не установлена!"
echo " Нужно добавить в docker-compose.yml и перезапустить контейнер"
else
echo " ✓ OLLAMA_BASE_URL=$OLLAMA_URL"
fi
echo ""
echo "2. Проверка доступности Ollama из Open WebUI..."
if $DOCKER_CMD exec open-webui curl -s --max-time 5 http://ollama:11434/api/tags >/dev/null 2>&1; then
echo " ✓ Ollama доступен по адресу http://ollama:11434"
else
echo " ✗ Ollama недоступен из Open WebUI"
fi
echo ""
echo "3. Проверка модели gemma3n:e4b-it-fp16..."
MODELS=$($DOCKER_CMD exec open-webui curl -s http://ollama:11434/api/tags 2>/dev/null)
if echo "$MODELS" | grep -q "gemma3n:e4b-it-fp16"; then
echo " ✓ Модель найдена"
else
echo " ✗ Модель не найдена"
fi
echo ""
echo "4. Проверка логов Open WebUI на наличие запросов с изображениями..."
RECENT_LOGS=$($DOCKER_CMD logs open-webui --tail 100 2>&1)
if echo "$RECENT_LOGS" | grep -qi "image.*ollama\|ollama.*image\|vision\|multimodal"; then
echo " ✓ Найдены упоминания изображений в логах:"
echo "$RECENT_LOGS" | grep -i "image.*ollama\|ollama.*image\|vision\|multimodal" | tail -5
else
echo " ⚠ Нет упоминаний изображений в последних логах"
fi
echo ""
echo "5. Проверка логов Ollama на наличие запросов с изображениями..."
OLLAMA_LOGS=$($DOCKER_CMD logs ollama --tail 100 2>&1)
if echo "$OLLAMA_LOGS" | grep -qi "image\|vision\|multimodal"; then
echo " ✓ Найдены запросы с изображениями в логах Ollama:"
echo "$OLLAMA_LOGS" | grep -i "image\|vision\|multimodal" | tail -5
else
echo " ✗ Нет запросов с изображениями в логах Ollama"
echo " Это означает, что изображения не доходят до Ollama!"
fi
echo ""
echo "6. Рекомендации:"
echo ""
if [ -z "$OLLAMA_URL" ]; then
echo " ⚠ КРИТИЧНО: Добавьте OLLAMA_BASE_URL в docker-compose.yml:"
echo " - OLLAMA_BASE_URL=http://ollama:11434"
echo " Затем: docker compose restart open-webui"
echo ""
fi
echo " Для диагностики проблемы с изображениями:"
echo " 1. Убедитесь, что в Settings → Connections → Ollama API"
echo " адрес установлен: http://ollama:11434"
echo ""
echo " 2. Попробуйте отправить изображение через веб-интерфейс"
echo " и сразу проверьте логи:"
echo " sudo docker logs open-webui --tail 50 -f"
echo " sudo docker logs ollama --tail 50 -f"
echo ""
echo " 3. Проверьте формат изображения (должен быть JPEG/PNG)"
echo " и размер (не слишком большой)"
echo ""
echo "=== Проверка завершена ==="

43
scripts/check_searxng_json.sh Executable file
View File

@@ -0,0 +1,43 @@
#!/bin/sh
# Скрипт для проверки формата JSON ответа от SearXNG
echo "Проверка формата JSON ответа от SearXNG..."
# Проверяем формат ответа от SearXNG
RESPONSE=$(curl -s "http://searxng:8080/search?q=test&format=json" 2>&1)
if [ $? -eq 0 ]; then
echo "✓ SearXNG отвечает"
echo "Формат ответа (первые 500 символов):"
echo "$RESPONSE" | head -c 500
echo ""
echo ""
# Проверяем наличие ключевых полей
if echo "$RESPONSE" | grep -q '"results"'; then
echo "✓ Найдено поле 'results'"
fi
if echo "$RESPONSE" | grep -q '"url"'; then
echo "✓ Найдено поле 'url'"
fi
if echo "$RESPONSE" | grep -q '"link"'; then
echo "✓ Найдено поле 'link'"
fi
if echo "$RESPONSE" | grep -q '"title"'; then
echo "✓ Найдено поле 'title'"
fi
if echo "$RESPONSE" | grep -q '"content"'; then
echo "✓ Найдено поле 'content'"
fi
if echo "$RESPONSE" | grep -q '"snippet"'; then
echo "✓ Найдено поле 'snippet'"
fi
else
echo "✗ Ошибка при запросе к SearXNG"
echo "$RESPONSE"
fi

42
scripts/check_vision_models.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Проверка доступных vision моделей в Ollama
set -e
CONTAINER_OLLAMA="ollama"
echo "=== Проверка vision моделей в Ollama ==="
echo ""
# Определяем команду docker
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
echo "1. Список установленных моделей:"
$DOCKER_CMD exec $CONTAINER_OLLAMA ollama list 2>/dev/null || sudo $DOCKER_CMD exec $CONTAINER_OLLAMA ollama list 2>/dev/null
echo ""
echo "2. Популярные vision модели для Ollama:"
echo ""
echo " Рекомендуемые модели с поддержкой vision:"
echo " - llava:latest (LLaVA 1.6) - 7B параметров, хорошо работает с изображениями"
echo " - bakllava:latest (BakLLaVA) - 7B параметров, Mistral + LLaVA"
echo " - llama3.2-vision:latest (Llama 3.2 Vision) - 11B параметров"
echo " - gemma2:9b-it (Gemma 2) - может поддерживать vision"
echo ""
echo "3. Для установки vision модели выполните:"
echo ""
echo " sudo docker exec ollama ollama pull llava:latest"
echo " # или"
echo " sudo docker exec ollama ollama pull bakllava:latest"
echo ""
echo "4. Проверка текущей модели gemma3n:e4b-it-fp16:"
echo ""
echo " Модель gemma3n:e4b-it-fp16 может не поддерживать vision правильно."
echo " Рекомендуется использовать специализированные vision модели:"
echo " - llava:latest (лучший выбор для vision)"
echo " - bakllava:latest (альтернатива)"
echo ""
echo "=== Готово ==="

90
scripts/diagnose_search.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
# Диагностика проблемы с поиском в Open WebUI
echo "=== ДИАГНОСТИКА ПОИСКА В OPEN WEBUI ==="
echo ""
# 1. Проверка SearXNG
echo "1. Проверка SearXNG..."
SEARXNG_STATUS=$(docker ps | grep searxng | awk '{print $7}')
if [ "$SEARXNG_STATUS" = "healthy" ] || [ "$SEARXNG_STATUS" = "Up" ]; then
echo "✓ SearXNG работает (статус: $SEARXNG_STATUS)"
else
echo "✗ SearXNG не работает (статус: $SEARXNG_STATUS)"
fi
# 2. Проверка JSON формата
echo ""
echo "2. Проверка JSON формата SearXNG..."
JSON_TEST=$(docker exec open-webui curl -s "http://searxng:8080/search?q=test&format=json" 2>&1 | head -c 200)
if echo "$JSON_TEST" | grep -q "results"; then
echo "✓ JSON формат работает"
else
echo "✗ JSON формат не работает"
echo " Ответ: $JSON_TEST"
fi
# 3. Проверка патча User-Agent
echo ""
echo "3. Проверка патча User-Agent..."
RAG_BOT_FOUND=$(docker exec open-webui grep -r "RAG Bot" /app/backend/open_webui/routers/retrieval.py /app/backend/open_webui/utils/middleware.py 2>/dev/null | wc -l)
if [ "$RAG_BOT_FOUND" -eq 0 ]; then
echo "✓ Патч User-Agent применен (проблемная строка не найдена)"
else
echo "✗ Патч User-Agent НЕ применен (найдено вхождений: $RAG_BOT_FOUND)"
echo " Нужно перезапустить Open WebUI для применения патча"
fi
# 4. Проверка логов Open WebUI на ошибки
echo ""
echo "4. Последние ошибки в логах Open WebUI..."
docker logs open-webui --tail 50 2>&1 | grep -i "error\|user-agent\|invalid\|searxng" | tail -10
if [ $? -ne 0 ]; then
echo " (Ошибок не найдено в последних 50 строках)"
fi
# 5. Проверка конфигурации docker-compose
echo ""
echo "5. Проверка конфигурации..."
SEARXNG_URL=$(grep "SEARXNG_QUERY_URL" docker-compose.yml | head -1)
echo " SEARXNG_QUERY_URL: $SEARXNG_URL"
if echo "$SEARXNG_URL" | grep -q "format=json"; then
echo "✓ URL содержит format=json"
else
echo "⚠ URL не содержит format=json явно"
fi
# 6. Проверка settings.yml
echo ""
echo "6. Проверка settings.yml SearXNG..."
if grep -q "formats:" searxng/settings.yml && grep -q "json" searxng/settings.yml; then
echo "✓ JSON формат включен в settings.yml"
else
echo "✗ JSON формат НЕ найден в settings.yml"
fi
if grep -q "limiter: false" searxng/settings.yml; then
echo "✓ Лимитер отключен"
else
echo "⚠ Лимитер может быть включен"
fi
echo ""
echo "=== РЕКОМЕНДАЦИИ ==="
echo ""
if [ "$RAG_BOT_FOUND" -gt 0 ]; then
echo "1. Перезапустите Open WebUI для применения патча User-Agent:"
echo " sudo docker restart open-webui"
echo ""
fi
if ! echo "$JSON_TEST" | grep -q "results"; then
echo "2. Исправьте конфигурацию SearXNG:"
echo " sudo ./scripts/fix_searxng_config.sh"
echo ""
fi
echo "3. Проверьте настройки в интерфейсе Open WebUI:"
echo " Settings → Web Search"
echo " URL должен быть: http://searxng:8080/search?q=<query>&format=json"
echo ""

32
scripts/find_model_image_api.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Поиск API endpoint для изображения профиля модели
CONTAINER_NAME="open-webui"
echo "=== Поиск API endpoint /api/v1/models/model/profile/image ==="
echo ""
echo "1. Поиск Python файлов с этим endpoint..."
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
-exec grep -l "model/profile/image\|profile/image\|models.*profile" {} \; 2>/dev/null
echo ""
echo "2. Поиск в main.py и routes..."
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
\( -name "*main.py" -o -name "*route*.py" -o -name "*api*.py" -o -name "*model*.py" \) \
-exec grep -l "profile.*image\|image.*profile" {} \; 2>/dev/null
echo ""
echo "3. Поиск строк с '/api/v1/models'..."
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
-exec grep -l "/api/v1/models\|api/v1/models" {} \; 2>/dev/null | head -10
echo ""
echo "4. Поиск в шаблонах HTML/Svelte с этим API..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" \
-exec grep -l "model/profile/image\|models.*profile.*image" {} \; 2>/dev/null | head -10
echo ""
echo "=== Поиск завершен ==="

64
scripts/find_openwebui_text.sh Executable file
View File

@@ -0,0 +1,64 @@
#!/bin/bash
# Скрипт для поиска всех упоминаний "(Open WebUI)" в контейнере
CONTAINER_NAME="open-webui"
echo "=== Поиск всех упоминаний '(Open WebUI)' ==="
echo ""
# Ищем во всех файлах
echo "1. Поиск в HTML/Svelte файлах..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "(Open WebUI)" "$file" 2>/dev/null; then
echo " НАЙДЕНО в: $file"
docker exec "${CONTAINER_NAME}" grep -n "(Open WebUI)" "$file" 2>/dev/null | head -3
fi
done
echo ""
echo "2. Поиск в JS/TS файлах..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" \) \
! -path "*/node_modules/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "(Open WebUI)" "$file" 2>/dev/null; then
echo " НАЙДЕНО в: $file"
docker exec "${CONTAINER_NAME}" grep -n "(Open WebUI)" "$file" 2>/dev/null | head -3
fi
done
echo ""
echo "3. Поиск в скомпилированных файлах..."
docker exec "${CONTAINER_NAME}" find /app/web/build -type f -name "*.js" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "(Open WebUI)" "$file" 2>/dev/null; then
echo " НАЙДЕНО в скомпилированном: $file"
docker exec "${CONTAINER_NAME}" grep -o ".{0,50}(Open WebUI).{0,50}" "$file" 2>/dev/null | head -2
fi
done
echo ""
echo "4. Поиск в JSON файлах..."
docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.json" \
! -path "*/node_modules/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "(Open WebUI)" "$file" 2>/dev/null; then
echo " НАЙДЕНО в: $file"
docker exec "${CONTAINER_NAME}" grep -n "(Open WebUI)" "$file" 2>/dev/null | head -3
fi
done
echo ""
echo "5. Поиск вариантов написания..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \
! -path "*/node_modules/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -qE "iiEasyWeb.*Open|Open.*WebUI" "$file" 2>/dev/null; then
echo " ВАРИАНТ в: $file"
docker exec "${CONTAINER_NAME}" grep -nE "iiEasyWeb.*Open|Open.*WebUI" "$file" 2>/dev/null | head -2
fi
done
echo ""
echo "=== Поиск завершен ==="

View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Поиск элементов настроек, которые нужно удалить
CONTAINER_NAME="open-webui"
echo "=== Поиск элементов настроек ==="
echo ""
echo "1. Поиск 'Проверить обновления'..."
docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.svelte" -o -name "*.js" -o -name "*.ts" -o -name "*.html" \) \
! -path "*/node_modules/*" \
-exec grep -l "Проверить обновления\|Check for updates\|check.*update" {} \; 2>/dev/null | head -10
echo ""
echo "2. Поиск 'последняя' и GitHub releases..."
docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.svelte" -o -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" \
-exec grep -l "последняя\|latest\|github.com/open-webui/releases" {} \; 2>/dev/null | head -10
echo ""
echo "3. Поиск блока 'Помощь' и соцсетей..."
docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.svelte" -o -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" \
-exec grep -l "Помощь\|Help\|discord\.gg\|twitter\.com\|github.com/open-webui" {} \; 2>/dev/null | head -10
echo ""
echo "4. Поиск блока 'Лицензия'..."
docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.svelte" -o -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" \
-exec grep -l "Лицензия\|License\|лицензионный тарифный план" {} \; 2>/dev/null | head -10
echo ""
echo "5. Поиск в скомпилированных файлах..."
docker exec "${CONTAINER_NAME}" find /app/web/build -type f -name "*.js" \
-exec grep -l "Проверить обновления\|последняя\|Помощь\|Лицензия" {} \; 2>/dev/null | head -5
echo ""
echo "=== Поиск завершен ==="

49
scripts/fix_openwebui.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/bash
# Скрипт восстановления Open WebUI после повреждения ребрендингом
set -e
CONTAINER_NAME="open-webui"
echo "=== Восстановление Open WebUI ==="
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден."
exit 1
fi
echo "1. Остановка контейнера..."
docker stop "${CONTAINER_NAME}" 2>/dev/null || true
echo "2. Удаление поврежденного контейнера..."
docker rm "${CONTAINER_NAME}" 2>/dev/null || true
echo "3. Пересоздание контейнера..."
cd "$(dirname "$0")/.."
docker compose up -d open-webui
echo "4. Ожидание запуска контейнера..."
sleep 15
echo "5. Проверка статуса..."
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "✓ Контейнер запущен успешно"
# Проверяем, что контейнер работает
if docker exec "${CONTAINER_NAME}" curl -f http://localhost:8080/health 2>/dev/null; then
echo "✓ Контейнер отвечает на запросы"
else
echo "⚠ Контейнер запущен, но не отвечает. Проверьте логи: docker compose logs open-webui"
fi
else
echo "✗ Контейнер не запустился. Проверьте логи: docker compose logs open-webui"
exit 1
fi
echo ""
echo "=== Восстановление завершено ==="
echo ""
echo "ВАЖНО: Скрипт rebrand.sh был исправлен и больше не будет ломать код."
echo "Если нужно применить ребрендинг, используйте обновленный скрипт:"
echo " ./scripts/rebrand.sh"

56
scripts/fix_search_complete.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
# Полное исправление поиска в Open WebUI
# Исправляет конфигурацию SearXNG и перезапускает контейнеры
echo "=== ПОЛНОЕ ИСПРАВЛЕНИЕ ПОИСКА ==="
echo ""
# 1. Исправляем конфигурацию SearXNG
echo "1. Исправление конфигурации SearXNG..."
./scripts/fix_searxng_config.sh
# 2. Перезапускаем Open WebUI для применения патча User-Agent
echo ""
echo "2. Перезапуск Open WebUI для применения патча User-Agent..."
docker restart open-webui
echo ""
echo "Ожидание запуска Open WebUI (15 секунд)..."
sleep 15
# 3. Проверка
echo ""
echo "3. Финальная проверка..."
echo ""
# Проверка SearXNG
SEARXNG_STATUS=$(docker ps | grep searxng | awk '{print $7}')
if [ "$SEARXNG_STATUS" = "healthy" ] || [ "$SEARXNG_STATUS" = "Up" ]; then
echo "✓ SearXNG работает"
else
echo "✗ SearXNG не работает"
fi
# Проверка JSON
JSON_TEST=$(docker exec open-webui curl -s "http://searxng:8080/search?q=test&format=json" 2>&1 | head -c 200)
if echo "$JSON_TEST" | grep -q "results"; then
echo "✓ JSON формат работает"
else
echo "✗ JSON формат не работает"
fi
# Проверка патча
RAG_BOT_FOUND=$(docker exec open-webui grep -r "RAG Bot" /app/backend/open_webui/routers/retrieval.py /app/backend/open_webui/utils/middleware.py 2>/dev/null | wc -l)
if [ "$RAG_BOT_FOUND" -eq 0 ]; then
echo "✓ Патч User-Agent применен"
else
echo "⚠ Патч User-Agent может быть не применен (найдено: $RAG_BOT_FOUND)"
fi
echo ""
echo "=== ГОТОВО ==="
echo ""
echo "Проверьте поиск в Open WebUI:"
echo "1. Откройте Settings → Web Search"
echo "2. URL должен быть: http://searxng:8080/search?q=<query>&format=json"
echo "3. Попробуйте поиск в чате"

55
scripts/fix_searxng_config.sh Executable file
View File

@@ -0,0 +1,55 @@
#!/bin/sh
# Скрипт для исправления конфигурации SearXNG после перезапуска контейнера
echo "Исправление конфигурации SearXNG..."
# Исправляем файл на хосте (он монтируется в контейнер)
cat > /home/its/iiEasyWeb/searxng/settings.yml << 'EOF'
# SearXNG Settings для работы с Open WebUI
# Этот файл включает поддержку JSON формата для API запросов
use_default_settings: true
server:
secret_key: "CHANGE_ME_SECRET_KEY"
bind_address: "0.0.0.0"
port: 8080
limiter: false
method: "GET"
search:
safe_search: 0
autocomplete: "google"
formats:
- html
- json
general:
instance_name: "SearXNG"
debug: false
EOF
echo "✓ Конфигурация обновлена на хосте"
# Перезапускаем SearXNG
echo "Перезапуск SearXNG..."
docker restart searxng
echo ""
echo "Ожидание запуска SearXNG (10 секунд)..."
sleep 10
# Проверяем, что JSON формат работает
echo ""
echo "Проверка JSON формата..."
RESPONSE=$(docker exec open-webui curl -s "http://searxng:8080/search?q=test&format=json" 2>&1 | head -c 200)
if echo "$RESPONSE" | grep -q "results"; then
echo "✓ JSON формат работает! Поиск должен работать в Open WebUI."
else
echo "⚠ Предупреждение: JSON формат может быть недоступен. Проверьте логи:"
echo " docker logs searxng --tail 50"
fi
echo ""
echo "Готово! Проверьте поиск в Open WebUI."

31
scripts/fix_searxng_json.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
# Скрипт для исправления конфигурации SearXNG для работы с JSON форматом
echo "Исправление конфигурации SearXNG для JSON формата..."
# 1. Убеждаемся, что лимитер отключен
echo "1. Отключение лимитера..."
docker exec searxng sed -i 's/limiter: true/limiter: false/g' /etc/searxng/settings.yml 2>/dev/null || echo " Лимитер уже отключен или настройка не найдена"
# 2. Обновляем секцию search с правильными форматами
echo "2. Обновление секции search..."
docker exec searxng sh -c "sed -i '/^search:/,\$d' /etc/searxng/settings.yml && cat >> /etc/searxng/settings.yml <<'EOF'
search:
safe_search: 0
autocomplete: 'google'
formats:
- html
- json
EOF"
# 3. Перезапускаем SearXNG
echo "3. Перезапуск SearXNG..."
docker restart searxng
echo ""
echo "✓ Конфигурация SearXNG обновлена!"
echo " - JSON формат включен"
echo " - Лимитер отключен"
echo " - Autocomplete: google"
echo ""
echo "Подождите 10-15 секунд для полного запуска SearXNG..."

57
scripts/fix_trace_error.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
# Скрипт для исправления ошибки NameError: name 'trace' is not defined
# Пересоздает контейнер Open WebUI с чистой версией
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
CONTAINER_NAME="open-webui"
echo "=== Исправление ошибки NameError: name 'trace' is not defined ==="
echo ""
cd "$PROJECT_DIR"
echo "1. Остановка контейнера..."
sudo docker compose stop "$CONTAINER_NAME" 2>/dev/null || true
echo "2. Удаление поврежденного контейнера..."
sudo docker compose rm -f "$CONTAINER_NAME" 2>/dev/null || true
echo "3. Пересоздание контейнера с чистой версией..."
sudo docker compose up -d "$CONTAINER_NAME"
echo "4. Ожидание запуска контейнера (30 секунд)..."
sleep 30
echo "5. Проверка статуса..."
if sudo docker compose ps "$CONTAINER_NAME" | grep -q "Up"; then
echo "✓ Контейнер запущен успешно"
else
echo "✗ Контейнер не запустился. Проверьте логи:"
echo " sudo docker compose logs $CONTAINER_NAME"
exit 1
fi
echo ""
echo "6. Проверка логов на ошибки..."
ERRORS=$(sudo docker compose logs "$CONTAINER_NAME" --tail 50 2>&1 | grep -i "trace\|error" || true)
if [ -z "$ERRORS" ]; then
echo "✓ Ошибок не найдено"
else
echo "⚠ Найдены ошибки в логах:"
echo "$ERRORS"
fi
echo ""
echo "=== Готово! ==="
echo ""
echo "Теперь проверьте:"
echo "1. Откройте https://odo.iieasy.ru"
echo "2. Должна появиться страница входа с формой и кнопкой 'iiEasy ID'"
echo "3. Если нужно применить логотипы, используйте Admin Panel:"
echo " Settings → Appearance → Logo"
echo ""
echo "Если ошибка 'trace' осталась, проверьте логи:"
echo " sudo docker compose logs $CONTAINER_NAME --tail 100"

132
scripts/fix_user_agent.sh Executable file
View File

@@ -0,0 +1,132 @@
#!/bin/sh
# Исправление бага с User-Agent в Open WebUI v0.8.3
# Проблема: User-Agent начинается с пробела, что вызывает ошибку "Invalid leading whitespace"
echo "Применение патча для исправления User-Agent..."
# Исправляем в retrieval.py
FILE="/app/backend/open_webui/routers/retrieval.py"
if [ -f "$FILE" ]; then
echo "Обработка файла: $FILE"
# Ищем все варианты проблемной строки (более агрессивный поиск)
PROBLEM_FOUND=0
# Проверяем наличие проблемной строки в разных вариантах
if grep -qE "(github\.com/open-webui|RAG Bot|https://github)" "$FILE" 2>/dev/null; then
PROBLEM_FOUND=1
fi
if [ "$PROBLEM_FOUND" -eq 1 ] || grep -q "User-Agent" "$FILE" 2>/dev/null; then
echo " Найдены строки с User-Agent, применяем патч..."
# Более агрессивная замена - ищем любые варианты с пробелом в начале
# Исправляем варианты с одинарными кавычками
sed -i "s/' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$FILE"
sed -i "s/ '(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$FILE"
sed -i "s/'\(https:\/\/github\.com\/open-webui\/open-webui\) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$FILE"
# Исправляем варианты с двойными кавычками
sed -i 's/" (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$FILE"
sed -i 's/ "(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$FILE"
sed -i 's/"\(https:\/\/github\.com\/open-webui\/open-webui\) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$FILE"
# Исправляем варианты без кавычек
sed -i "s/ (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot/Open-WebUI-RAG-Bot/g" "$FILE"
sed -i "s/ \(https:\/\/github\.com\/open-webui\/open-webui\) RAG Bot/Open-WebUI-RAG-Bot/g" "$FILE"
# Исправляем если используется в headers dict с пробелом
sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE"
sed -i "s/'User-Agent': ' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$FILE"
sed -i 's/"User-Agent": "(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE"
# Исправляем f-string или конкатенацию
sed -i 's/User-Agent.*github\.com.*open-webui.*RAG Bot/User-Agent": "Open-WebUI-RAG-Bot/g' "$FILE"
# Универсальная замена - ищем любую строку с пробелом перед User-Agent значением
sed -i 's/"User-Agent": " [^"]*RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE"
sed -i "s/'User-Agent': ' [^']*RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$FILE"
# Исправляем вариант "External Web Loader"
sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) External Web Loader"/"User-Agent": "Open-WebUI-External-Web-Loader"/g' "$FILE"
# Универсальная замена для любых User-Agent с пробелом и github.com/open-webui
sed -i 's/"User-Agent": " \([^"]*github\.com\/open-webui[^"]*\)"/"User-Agent": "Open-WebUI-Bot"/g' "$FILE"
sed -i "s/'User-Agent': ' \([^']*github\.com\/open-webui[^']*\)'/'User-Agent': 'Open-WebUI-Bot'/g" "$FILE"
echo "✓ Патч применен к $FILE"
else
echo " Проблемная строка не найдена в $FILE (возможно, уже исправлена)"
fi
else
echo "⚠ Файл $FILE не найден"
fi
# Исправляем в middleware.py
FILE2="/app/backend/open_webui/utils/middleware.py"
if [ -f "$FILE2" ]; then
echo "Обработка файла: $FILE2"
PROBLEM_FOUND2=0
if grep -qE "(github\.com/open-webui|RAG Bot|https://github)" "$FILE2" 2>/dev/null; then
PROBLEM_FOUND2=1
fi
if [ "$PROBLEM_FOUND2" -eq 1 ] || grep -q "User-Agent" "$FILE2" 2>/dev/null; then
echo " Найдены строки с User-Agent, применяем патч..."
# Те же замены что и для retrieval.py
sed -i "s/' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$FILE2"
sed -i "s/ '(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$FILE2"
sed -i 's/" (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$FILE2"
sed -i 's/ "(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$FILE2"
sed -i "s/ (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot/Open-WebUI-RAG-Bot/g" "$FILE2"
sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE2"
sed -i "s/'User-Agent': ' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$FILE2"
sed -i 's/"User-Agent": "(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE2"
sed -i 's/User-Agent.*github\.com.*open-webui.*RAG Bot/User-Agent": "Open-WebUI-RAG-Bot/g' "$FILE2"
sed -i 's/"User-Agent": " [^"]*RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$FILE2"
sed -i "s/'User-Agent': ' [^']*RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$FILE2"
# Исправляем вариант "External Web Loader"
sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) External Web Loader"/"User-Agent": "Open-WebUI-External-Web-Loader"/g' "$FILE2"
# Универсальная замена для любых User-Agent с пробелом и github.com/open-webui
sed -i 's/"User-Agent": " \([^"]*github\.com\/open-webui[^"]*\)"/"User-Agent": "Open-WebUI-Bot"/g' "$FILE2"
sed -i "s/'User-Agent': ' \([^']*github\.com\/open-webui[^']*\)'/'User-Agent': 'Open-WebUI-Bot'/g" "$FILE2"
echo "✓ Патч применен к $FILE2"
else
echo " Проблемная строка не найдена в $FILE2 (возможно, уже исправлена)"
fi
fi
# Ищем в других возможных файлах (более агрессивный поиск)
echo "Поиск проблемной строки во всех Python файлах..."
find /app/backend -name "*.py" -type f 2>/dev/null | while read pyfile; do
if [ "$pyfile" != "$FILE" ] && [ "$pyfile" != "$FILE2" ]; then
# Проверяем наличие проблемной строки в любом виде
if grep -qE "(github\.com/open-webui|RAG Bot|https://github)" "$pyfile" 2>/dev/null; then
echo " Обработка файла: $pyfile"
# Применяем все варианты замены
sed -i "s/' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$pyfile"
sed -i "s/ '(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$pyfile"
sed -i 's/" (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$pyfile"
sed -i 's/ "(https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$pyfile"
sed -i "s/ (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot/Open-WebUI-RAG-Bot/g" "$pyfile"
sed -i 's/"User-Agent": " [^"]*RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$pyfile"
sed -i "s/'User-Agent': ' [^']*RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$pyfile"
# Исправляем вариант "External Web Loader"
sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) External Web Loader"/"User-Agent": "Open-WebUI-External-Web-Loader"/g' "$pyfile"
# Универсальная замена
sed -i 's/"User-Agent": " \([^"]*github\.com\/open-webui[^"]*\)"/"User-Agent": "Open-WebUI-Bot"/g' "$pyfile"
sed -i "s/'User-Agent': ' \([^']*github\.com\/open-webui[^']*\)'/'User-Agent': 'Open-WebUI-Bot'/g" "$pyfile"
fi
fi
done
# Удаляем скомпилированные Python файлы (.pyc), чтобы они пересобрались
echo "Очистка скомпилированных файлов Python..."
find /app/backend -name "*.pyc" -delete 2>/dev/null
find /app/backend -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
echo "Патч применен. Запуск Open WebUI..."

View File

@@ -0,0 +1,59 @@
#!/bin/sh
# Агрессивное исправление бага с User-Agent в Open WebUI
# Ищет и исправляет проблемную строку во всех возможных местах
echo "=== АГРЕССИВНОЕ ИСПРАВЛЕНИЕ USER-AGENT ==="
echo ""
# Находим все файлы с проблемной строкой
echo "Поиск всех файлов с проблемной строкой User-Agent..."
PROBLEM_FILES=$(docker exec open-webui find /app/backend -name "*.py" -type f -exec grep -l "github.com/open-webui" {} \; 2>/dev/null)
if [ -z "$PROBLEM_FILES" ]; then
echo "Файлы не найдены через docker exec, пробуем другой способ..."
# Альтернативный способ - ищем через grep в контейнере
docker exec open-webui sh -c 'find /app/backend -name "*.py" -type f | xargs grep -l "github.com/open-webui" 2>/dev/null' | while read pyfile; do
if [ -n "$pyfile" ]; then
echo "Исправление файла: $pyfile"
docker exec open-webui sed -i "s/' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$pyfile"
docker exec open-webui sed -i 's/" (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$pyfile"
docker exec open-webui sed -i "s/ (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot/Open-WebUI-RAG-Bot/g" "$pyfile"
docker exec open-webui sed -i 's/"User-Agent": " [^"]*RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$pyfile"
docker exec open-webui sed -i "s/'User-Agent': ' [^']*RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$pyfile"
fi
done
else
echo "$PROBLEM_FILES" | while read pyfile; do
echo "Исправление файла: $pyfile"
docker exec open-webui sed -i "s/' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'Open-WebUI-RAG-Bot'/g" "$pyfile"
docker exec open-webui sed -i 's/" (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"Open-WebUI-RAG-Bot"/g' "$pyfile"
docker exec open-webui sed -i "s/ (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot/Open-WebUI-RAG-Bot/g" "$pyfile"
docker exec open-webui sed -i 's/"User-Agent": " [^"]*RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' "$pyfile"
docker exec open-webui sed -i "s/'User-Agent': ' [^']*RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" "$pyfile"
done
fi
# Очищаем кеш Python
echo ""
echo "Очистка кеша Python..."
docker exec open-webui find /app/backend -name "*.pyc" -delete 2>/dev/null
docker exec open-webui find /app/backend -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
# Проверяем результат
echo ""
echo "Проверка результата..."
RAG_BOT_COUNT=$(docker exec open-webui grep -r "github.com/open-webui.*RAG Bot" /app/backend 2>/dev/null | wc -l)
if [ "$RAG_BOT_COUNT" -eq 0 ]; then
echo "✓ Проблемная строка не найдена - патч применен успешно"
else
echo "⚠ Найдено вхождений проблемной строки: $RAG_BOT_COUNT"
echo "Проблемные файлы:"
docker exec open-webui grep -r "github.com/open-webui.*RAG Bot" /app/backend 2>/dev/null | cut -d: -f1 | sort -u
fi
echo ""
echo "Перезапуск Open WebUI..."
docker restart open-webui
echo ""
echo "Готово! Подождите 15 секунд и проверьте поиск."

42
scripts/fix_user_agent_final.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/sh
# Финальное исправление всех вариантов User-Agent с пробелом в начале
echo "=== ФИНАЛЬНОЕ ИСПРАВЛЕНИЕ USER-AGENT ==="
echo ""
# Исправляем "External Web Loader" вариант
echo "Исправление external_web.py..."
docker exec open-webui sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) External Web Loader"/"User-Agent": "Open-WebUI-External-Web-Loader"/g' /app/backend/open_webui/retrieval/loaders/external_web.py
# Исправляем "RAG Bot" вариант (на всякий случай еще раз)
echo "Исправление всех вариантов RAG Bot..."
docker exec open-webui find /app/backend -name "*.py" -type f -exec sed -i 's/"User-Agent": " (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot"/"User-Agent": "Open-WebUI-RAG-Bot"/g' {} \;
docker exec open-webui find /app/backend -name "*.py" -type f -exec sed -i "s/'User-Agent': ' (https:\/\/github\.com\/open-webui\/open-webui) RAG Bot'/'User-Agent': 'Open-WebUI-RAG-Bot'/g" {} \;
# Универсальная замена - любой User-Agent с пробелом в начале
echo "Универсальная замена всех User-Agent с пробелом..."
docker exec open-webui find /app/backend -name "*.py" -type f -exec sed -i 's/"User-Agent": " \([^"]*github\.com\/open-webui[^"]*\)"/"User-Agent": "Open-WebUI-Bot"/g' {} \;
docker exec open-webui find /app/backend -name "*.py" -type f -exec sed -i "s/'User-Agent': ' \([^']*github\.com\/open-webui[^']*\)'/'User-Agent': 'Open-WebUI-Bot'/g" {} \;
# Очистка кеша
echo "Очистка кеша Python..."
docker exec open-webui find /app/backend -name "*.pyc" -delete 2>/dev/null
docker exec open-webui find /app/backend -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
# Проверка
echo ""
echo "Проверка результата..."
PROBLEM_COUNT=$(docker exec open-webui grep -rn '"User-Agent": " (' /app/backend --include="*.py" 2>/dev/null | wc -l)
if [ "$PROBLEM_COUNT" -eq 0 ]; then
echo "✓ Все проблемные строки исправлены!"
else
echo "⚠ Найдено проблемных строк: $PROBLEM_COUNT"
docker exec open-webui grep -rn '"User-Agent": " (' /app/backend --include="*.py" 2>/dev/null
fi
echo ""
echo "Перезапуск Open WebUI..."
docker restart open-webui
echo ""
echo "✓ Готово! Подождите 15 секунд и проверьте поиск."

35
scripts/init-logos.sh Normal file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
# Скрипт для автоматической замены логотипов при запуске контейнера
# Этот скрипт можно запускать при каждом старте контейнера
MEDIA_DIR="/app/media"
MAX_RETRIES=10
RETRY_DELAY=2
# Ждем пока контейнер полностью запустится
for i in $(seq 1 $MAX_RETRIES); do
if curl -f http://localhost:8080/health >/dev/null 2>&1; then
break
fi
sleep $RETRY_DELAY
done
# Находим все favicon и logo файлы
find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | while read file; do
dir=$(dirname "$file")
name=$(basename "$file")
# Заменяем favicon
if [[ "$name" == favicon* ]] && [ -f "$MEDIA_DIR/favicon.png" ]; then
cp "$MEDIA_DIR/favicon.png" "$file" 2>/dev/null || true
# Также создаем .ico
cp "$MEDIA_DIR/favicon.png" "$dir/favicon.ico" 2>/dev/null || true
fi
# Заменяем logo
if [[ "$name" == logo* ]] && [ -f "$MEDIA_DIR/logo.png" ]; then
cp "$MEDIA_DIR/logo.png" "$file" 2>/dev/null || true
# Также создаем .svg
cp "$MEDIA_DIR/logo.png" "$dir/logo.svg" 2>/dev/null || true
fi
done

45
scripts/init.sh Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
# Скрипт инициализации iiEasy AI-платформы
# Выполняет ребрендинг и загрузку модели Ollama
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
echo "=== Инициализация iiEasy AI-платформы ==="
echo ""
cd "$PROJECT_DIR"
# Проверка наличия контейнеров
if ! docker ps --format '{{.Names}}' | grep -q "^open-webui$"; then
echo "Ошибка: Контейнер open-webui не запущен. Запустите: docker compose up -d"
exit 1
fi
if ! docker ps --format '{{.Names}}' | grep -q "^ollama$"; then
echo "Ошибка: Контейнер ollama не запущен. Запустите: docker compose up -d"
exit 1
fi
# 1. Ребрендинг Open WebUI
echo "1. Применение ребрендинга Open WebUI..."
"$SCRIPT_DIR/rebrand.sh"
echo ""
echo "2. Загрузка модели Ollama (gemma3n:e4b-it-fp16)..."
echo " Это может занять несколько минут в зависимости от скорости интернета..."
docker exec ollama ollama pull gemma3n:e4b-it-fp16
echo ""
echo "3. Проверка загруженных моделей..."
docker exec ollama ollama list
echo ""
echo "=== Инициализация завершена! ==="
echo ""
echo "Проверьте:"
echo " - Open WebUI: https://odo.iieasy.ru"
echo " - Логотип и ребрендинг применены"
echo " - Модель gemma3n:e4b-it-fp16 доступна в Ollama"

58
scripts/install_vision_model.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
# Установка специализированной vision модели для Ollama
set -e
CONTAINER_OLLAMA="ollama"
MODEL_CHOICE="${1:-llava}"
echo "=== Установка Vision модели для Ollama ==="
echo ""
# Определяем команду docker
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
echo "Доступные vision модели:"
echo " 1. llava:latest (LLaVA 1.6) - 7B, лучший выбор для vision"
echo " 2. bakllava:latest (BakLLaVA) - 7B, Mistral + LLaVA"
echo " 3. llama3.2-vision:latest (Llama 3.2 Vision) - 11B, требует 8GB VRAM"
echo ""
if [ "$MODEL_CHOICE" = "llava" ]; then
MODEL="llava:latest"
echo "Выбрана модель: $MODEL (LLaVA 1.6)"
elif [ "$MODEL_CHOICE" = "bakllava" ]; then
MODEL="bakllava:latest"
echo "Выбрана модель: $MODEL (BakLLaVA)"
elif [ "$MODEL_CHOICE" = "llama3.2" ]; then
MODEL="llama3.2-vision:latest"
echo "Выбрана модель: $MODEL (Llama 3.2 Vision)"
else
MODEL="llava:latest"
echo "Используется модель по умолчанию: $MODEL"
fi
echo ""
echo "Загрузка модели $MODEL..."
echo "Это может занять несколько минут в зависимости от скорости интернета..."
echo ""
$DOCKER_CMD exec $CONTAINER_OLLAMA ollama pull "$MODEL" || {
echo "✗ Ошибка при загрузке модели"
exit 1
}
echo ""
echo "✓ Модель загружена!"
echo ""
echo "Проверка установленных моделей:"
$DOCKER_CMD exec $CONTAINER_OLLAMA ollama list
echo ""
echo "=== Готово! ==="
echo ""
echo "Теперь в Open WebUI выберите модель: $MODEL"
echo "И попробуйте загрузить изображение и задать вопрос о нем."

248
scripts/rebrand.sh Executable file
View File

@@ -0,0 +1,248 @@
#!/bin/bash
# Скрипт ребрендинга Open WebUI для iiEasy
# ВНИМАНИЕ: Этот скрипт может ломать OAuth!
# Рекомендуется использовать rebrand_complete.sh для полного ребрендинга
# Заменяет логотипы, favicon, удаляет упоминания Open WebUI, отключает проверку обновлений
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== Ребрендинг Open WebUI для iiEasy ==="
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден. Запустите docker-compose up -d сначала."
exit 1
fi
# Проверка, что контейнер запущен
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен. Запустите docker-compose up -d."
exit 1
fi
echo "1. Замена логотипов и favicon..."
# Важно: Open WebUI может использовать скомпилированные статические файлы
# Нужно найти правильные пути и заменить файлы там, где они реально используются
# Определяем пути для статических файлов в Open WebUI
# Open WebUI использует /app/web/build/_app/immutable/ для статических файлов
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
"/app/static"
"/app/public"
)
# Находим существующую директорию со статическими файлами
STATIC_DIR=""
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
STATIC_DIR="$dir"
echo " Найдена директория статических файлов: $STATIC_DIR"
break
fi
done
if [ -z "$STATIC_DIR" ]; then
echo " Предупреждение: Директория статических файлов не найдена, пробуем найти через поиск favicon..."
# Ищем где находятся существующие favicon файлы
FAVICON_PATH=$(docker exec "${CONTAINER_NAME}" find /app -name "favicon.png" -o -name "favicon.ico" 2>/dev/null | head -1)
if [ -n "$FAVICON_PATH" ]; then
STATIC_DIR=$(dirname "$FAVICON_PATH")
echo " Найдена директория через поиск favicon: $STATIC_DIR"
else
STATIC_DIR="/app/web/build/_app/immutable"
echo " Используем стандартный путь: $STATIC_DIR"
# Создаем директорию если её нет
docker exec "${CONTAINER_NAME}" mkdir -p "$STATIC_DIR" 2>/dev/null || true
fi
fi
# Копирование логотипов (приоритет: PNG > SVG)
# Копируем во все найденные директории
for target_dir in "$STATIC_DIR" "/app/web/build/_app/immutable" "/app/web/static" "/app/web/build"; do
if docker exec "${CONTAINER_NAME}" test -d "$target_dir" 2>/dev/null || [ "$target_dir" = "$STATIC_DIR" ]; then
echo " Копирование в $target_dir..."
# Логотипы
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${target_dir}/logo-dark.svg" 2>/dev/null || true
fi
# Favicon
if [ -f "$MEDIA_DIR/favicon.ico" ]; then
docker cp "$MEDIA_DIR/favicon.ico" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon-96x96.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.svg" ]; then
docker cp "$MEDIA_DIR/favicon.svg" "${CONTAINER_NAME}:${target_dir}/favicon.svg" 2>/dev/null || true
fi
fi
done
# Поиск и замена существующих favicon и logo файлов везде в /app
echo " Поиск существующих favicon и logo файлов для замены..."
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" \) 2>/dev/null | head -10)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | head -10)
echo " Найдено favicon файлов: $(echo "$EXISTING_FAVICONS" | wc -l)"
echo " Найдено logo файлов: $(echo "$EXISTING_LOGOS" | wc -l)"
# Заменяем существующие favicon файлы
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ]; then
echo " Замена: $favicon_file"
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
# Также создаем .ico версию рядом
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
done
fi
# Заменяем существующие logo файлы
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ]; then
echo " Замена: $logo_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
# Также копируем в корень public для веб-доступа
PUBLIC_DIRS=(
"/app/web/public"
"/app/public"
"/app/backend/public"
)
for pub_dir in "${PUBLIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$pub_dir" 2>/dev/null; then
echo " Копирование в $pub_dir..."
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${pub_dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.ico" 2>/dev/null || true
fi
break
fi
done
echo " Примечание: Если логотипы не изменились, настройте их через Admin Panel:"
echo " Settings → Appearance → Logo (загрузите файлы из /app/media/)"
echo "2. Поиск и замена текстовых упоминаний 'Open WebUI'..."
# Поиск файлов с упоминаниями Open WebUI в статических файлах и конфигурации
# ВАЖНО: ИСКЛЮЧАЕМ ВСЕ файлы, связанные с OAuth/Authentik/аутентификацией
# Это включает: oauth.py, auth.py, login.py, и все файлы в директориях oauth, oidc, auth, login
docker exec "${CONTAINER_NAME}" find /app -type f \( -name "*.py" -o -name "*.html" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.json" -o -name "*.svelte" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*oauth*" ! -name "*oidc*" ! -name "*auth*" ! -name "*login*" \
! -path "*/utils/oauth*" ! -path "*/utils/auth*" ! -path "*/backend/open_webui/utils/oauth*" \
-exec grep -l "Open WebUI\|open-webui\|openwebui\|\(Open WebUI\)" {} \; 2>/dev/null | while read file; do
echo " Обработка: $file"
# Замена "Open WebUI" на "iiEasyWeb" (только в тексте интерфейса, не в URL)
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
# Удаление "(Open WebUI)" в скобках - заменяем на пустую строку или только "iiEasyWeb"
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
# Замена "iiEasyWeb (Open WebUI)" на просто "iiEasyWeb"
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' "$file" 2>/dev/null || true
# ВАЖНО: НЕ заменяем open-webui в нижнем регистре, так как это может быть частью URL или конфигурации OAuth
done
# Специальная обработка для удаления "(Open WebUI)" из заголовков и описаний
echo "3. Удаление упоминаний '(Open WebUI)' из интерфейса..."
# ИСКЛЮЧАЕМ файлы OAuth/Authentik
docker exec "${CONTAINER_NAME}" find /app -type f \( -name "*.html" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.svelte" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "(Open WebUI)\|\(Open WebUI\)" {} \; 2>/dev/null | while read file; do
echo " Удаление '(Open WebUI)' из: $file"
# Удаляем различные варианты написания в скобках
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ (Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ \(Open WebUI\)//g' "$file" 2>/dev/null || true
done
echo "4. Отключение проверки обновлений..."
# Поиск и отключение проверки обновлений через GitHub API
# ИСКЛЮЧАЕМ файлы OAuth/Authentik
docker exec "${CONTAINER_NAME}" find /app/backend -type f \( -name "*.py" -o -name "*.js" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "github.com.*releases\|check.*update\|update.*check" {} \; 2>/dev/null | while read file; do
echo " Отключение проверки обновлений в: $file"
# Комментирование вызовов GitHub API для проверки обновлений
docker exec "${CONTAINER_NAME}" sed -i 's|https://api.github.com/repos/open-webui|# https://api.github.com/repos/open-webui|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|github.com/open-webui|# github.com/open-webui|g' "$file" 2>/dev/null || true
done
# Отключение проверки обновлений через переменные окружения (уже настроено в docker-compose.yml)
echo " Проверка обновлений отключена через переменные окружения"
echo "5. Удаление аналитики и телеметрии..."
# Поиск и отключение аналитики (более аккуратно, чтобы не сломать код)
# Комментируем только целые строки с импортами аналитики, а не части строк
# ИСКЛЮЧАЕМ файлы OAuth/Authentik
docker exec "${CONTAINER_NAME}" find /app/backend -type f \( -name "*.py" -o -name "*.js" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "from.*telemetry\|import.*telemetry\|analytics\|tracking\|gtag\|ga(\|google-analytics" {} \; 2>/dev/null | while read file; do
echo " Отключение аналитики в: $file"
# Комментируем только целые строки импорта, начинающиеся с from или import
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*from.*telemetry/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*import.*telemetry/s/^/# /' "$file" 2>/dev/null || true
done
echo "6. Удаление 'Powered by' футеров..."
# Поиск футеров с упоминанием Open WebUI
# ИСКЛЮЧАЕМ файлы OAuth/Authentik
docker exec "${CONTAINER_NAME}" find /app/backend -type f \( -name "*.html" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "Powered by\|powered by" {} \; 2>/dev/null | while read file; do
echo " Удаление футера в: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
done
echo "7. Перезапуск контейнера для применения изменений..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Не удалось перезапустить контейнер автоматически."
echo "Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== Ребрендинг завершен! ==="
echo ""
echo "Проверьте изменения:"
echo " 1. Откройте https://odo.iieasy.ru в браузере"
echo " 2. Проверьте логотип и favicon"
echo " 3. Проверьте отсутствие упоминаний 'Open WebUI'"
echo ""
echo "Примечание: Если изменения не отображаются, очистите кеш браузера."

126
scripts/rebrand_careful.sh Executable file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
# ОЧЕНЬ АККУРАТНЫЙ ребрендинг Open WebUI для iiEasy
# Только безопасные замены текста, НЕ трогает код
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== АККУРАТНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "⚠ Только безопасные замены текста в интерфейсе"
echo "⚠ Код Python/JS НЕ изменяется"
echo "⚠ OAuth/Authentik полностью защищены"
echo ""
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден."
exit 1
fi
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов и favicon..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
)
STATIC_DIR=""
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
STATIC_DIR="$dir"
break
fi
done
if [ -z "$STATIC_DIR" ]; then
FAVICON_PATH=$(docker exec "${CONTAINER_NAME}" find /app/web -name "favicon.png" -o -name "favicon.ico" 2>/dev/null | head -1)
if [ -n "$FAVICON_PATH" ]; then
STATIC_DIR=$(dirname "$FAVICON_PATH")
else
STATIC_DIR="/app/web/build/_app/immutable"
fi
fi
# Копирование логотипов
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${STATIC_DIR}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${STATIC_DIR}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${STATIC_DIR}/favicon.ico" 2>/dev/null || true
fi
echo "2. Замена текста 'Open WebUI' на 'iiEasyWeb' ТОЛЬКО в HTML/текстовых строках..."
# ТОЛЬКО фронтенд HTML/Svelte файлы - заменяем только в текстовом контенте
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
# Заменяем только в текстовом контенте между тегами, не в атрибутах или коде
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI" "$file" 2>/dev/null; then
echo " HTML/Svelte: $file"
# Заменяем только "Open WebUI" (с заглавными) в тексте, не трогаем код
docker exec "${CONTAINER_NAME}" sed -i 's/>Open WebUI</>iiEasyWeb</g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
fi
done
echo "3. Удаление '(Open WebUI)' из текста интерфейса..."
# Только удаляем текст в скобках из HTML
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "(Open WebUI)" "$file" 2>/dev/null; then
echo " Удаление скобок: $file"
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
fi
done
echo "4. Удаление 'Powered by Open WebUI' футеров..."
# Только удаляем строки с "Powered by"
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Powered by.*Open WebUI\|powered by.*Open WebUI" "$file" 2>/dev/null; then
echo " Удаление футера: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*Open WebUI/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*Open WebUI/d' "$file" 2>/dev/null || true
fi
done
echo ""
echo "✓ Изменены ТОЛЬКО текстовые строки в HTML/Svelte"
echo "✓ Код Python/JS НЕ изменялся"
echo "✓ OAuth/Authentik полностью защищены"
echo ""
echo "5. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== АККУРАТНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Все должно работать нормально"
echo " 3. Текст 'Open WebUI' заменен на 'iiEasyWeb' в интерфейсе"
echo ""
echo "Если что-то не работает, пересоздайте контейнер:"
echo " sudo docker compose stop open-webui"
echo " sudo docker compose rm -f open-webui"
echo " sudo docker compose up -d open-webui"

274
scripts/rebrand_complete.sh Executable file
View File

@@ -0,0 +1,274 @@
#!/bin/bash
# ПОЛНЫЙ ребрендинг Open WebUI для iiEasy
# Удаляет ВСЕ упоминания Open WebUI, отключает телеметрию
# НО защищает OAuth/Authentik файлы
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== ПОЛНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "✓ Удаление ВСЕХ упоминаний Open WebUI"
echo "✓ Отключение телеметрии и аналитики"
echo "✓ Защита OAuth/Authentik файлов"
echo ""
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден. Запустите docker-compose up -d сначала."
exit 1
fi
# Проверка, что контейнер запущен
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен. Запустите docker-compose up -d."
exit 1
fi
echo "1. Замена логотипов и favicon..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
"/app/static"
"/app/public"
)
STATIC_DIR=""
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
STATIC_DIR="$dir"
echo " Найдена директория: $STATIC_DIR"
break
fi
done
if [ -z "$STATIC_DIR" ]; then
FAVICON_PATH=$(docker exec "${CONTAINER_NAME}" find /app -name "favicon.png" -o -name "favicon.ico" 2>/dev/null | head -1)
if [ -n "$FAVICON_PATH" ]; then
STATIC_DIR=$(dirname "$FAVICON_PATH")
else
STATIC_DIR="/app/web/build/_app/immutable"
docker exec "${CONTAINER_NAME}" mkdir -p "$STATIC_DIR" 2>/dev/null || true
fi
fi
# Копирование логотипов
for target_dir in "$STATIC_DIR" "/app/web/build/_app/immutable" "/app/web/static" "/app/web/build"; do
if docker exec "${CONTAINER_NAME}" test -d "$target_dir" 2>/dev/null || [ "$target_dir" = "$STATIC_DIR" ]; then
echo " Копирование в $target_dir..."
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${target_dir}/logo-dark.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.ico" ]; then
docker cp "$MEDIA_DIR/favicon.ico" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon-96x96.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.svg" ]; then
docker cp "$MEDIA_DIR/favicon.svg" "${CONTAINER_NAME}:${target_dir}/favicon.svg" 2>/dev/null || true
fi
fi
done
# Замена существующих favicon и logo
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" \) 2>/dev/null | head -10)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | head -10)
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
done
fi
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
PUBLIC_DIRS=("/app/web/public" "/app/public" "/app/backend/public")
for pub_dir in "${PUBLIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$pub_dir" 2>/dev/null; then
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${pub_dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.ico" 2>/dev/null || true
fi
break
fi
done
echo "2. Удаление упоминаний 'Open WebUI' из фронтенда..."
# Изменяем ТОЛЬКО фронтенд файлы (веб-интерфейс)
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.svelte" -o -name "*.json" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI\|open-webui\|openwebui\|\(Open WebUI\)" "$file" 2>/dev/null; then
echo " Фронтенд: $file"
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/open-webui/iieasyweb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/openwebui/iieasyweb/g' "$file" 2>/dev/null || true
fi
done
echo "3. Удаление упоминаний 'Open WebUI' из бэкенда (кроме OAuth)..."
# Изменяем бэкенд Python файлы, НО исключаем OAuth/аутентификационные файлы
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*oauth*" ! -name "*oidc*" ! -name "*auth*" ! -name "*login*" \
! -path "*/utils/oauth*" ! -path "*/utils/auth*" \
! -path "*/open_webui/utils/oauth*" ! -path "*/open_webui/utils/auth*" \
! -path "*/open_webui/main.py" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI\|open-webui\|openwebui\|\(Open WebUI\)" "$file" 2>/dev/null; then
echo " Бэкенд: $file"
# Замена только текста, не URL или конфигурации
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
# НЕ заменяем open-webui/openwebui в бэкенде - может быть частью конфигурации
fi
done
echo "4. Отключение телеметрии и аналитики в бэкенде..."
# Отключаем телеметрию в Python файлах, НО исключаем OAuth файлы
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*oauth*" ! -name "*oidc*" ! -name "*auth*" ! -name "*login*" \
! -path "*/utils/oauth*" ! -path "*/utils/auth*" \
! -path "*/open_webui/utils/oauth*" ! -path "*/open_webui/utils/auth*" \
! -path "*/open_webui/main.py" \
-exec grep -l "from.*telemetry\|import.*telemetry\|analytics\|tracking\|gtag\|ga(\|google-analytics\|sentry\|posthog" {} \; 2>/dev/null | while read file; do
echo " Отключение телеметрии в: $file"
# Комментируем только целые строки импорта
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*from.*telemetry/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*import.*telemetry/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*from.*analytics/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*import.*analytics/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*from.*tracking/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*import.*tracking/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*from.*sentry/s/^/# /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/^[[:space:]]*import.*sentry/s/^/# /' "$file" 2>/dev/null || true
done
echo "5. Отключение телеметрии во фронтенде..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
-exec grep -l "telemetry\|analytics\|tracking\|gtag\|ga(\|google-analytics\|sentry\|posthog" {} \; 2>/dev/null | while read file; do
echo " Отключение телеметрии в: $file"
docker exec "${CONTAINER_NAME}" sed -i '/import.*telemetry/s/^/\/\/ /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/from.*telemetry/s/^/\/\/ /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/import.*analytics/s/^/\/\/ /' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/from.*analytics/s/^/\/\/ /' "$file" 2>/dev/null || true
done
echo "6. Отключение проверки обновлений..."
# Отключаем проверку обновлений в бэкенде (кроме OAuth)
docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*oauth*" ! -name "*oidc*" ! -name "*auth*" ! -name "*login*" \
! -path "*/utils/oauth*" ! -path "*/utils/auth*" \
! -path "*/open_webui/utils/oauth*" ! -path "*/open_webui/utils/auth*" \
! -path "*/open_webui/main.py" \
-exec grep -l "github.com.*releases\|check.*update\|update.*check" {} \; 2>/dev/null | while read file; do
echo " Отключение проверки обновлений в: $file"
docker exec "${CONTAINER_NAME}" sed -i 's|https://api.github.com/repos/open-webui|# https://api.github.com/repos/open-webui|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|github.com/open-webui|# github.com/open-webui|g' "$file" 2>/dev/null || true
done
# Отключаем проверку обновлений во фронтенде
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
-exec grep -l "github.com.*releases\|check.*update\|update.*check" {} \; 2>/dev/null | while read file; do
echo " Отключение проверки обновлений в: $file"
docker exec "${CONTAINER_NAME}" sed -i 's|https://api.github.com/repos/open-webui|// https://api.github.com/repos/open-webui|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|github.com/open-webui|// github.com/open-webui|g' "$file" 2>/dev/null || true
done
echo "7. Удаление 'Powered by' футеров..."
# Удаляем футеры из фронтенда
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Powered by\|powered by" "$file" 2>/dev/null; then
echo " Удаление футера из: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
fi
done
# Удаляем футеры из бэкенда (кроме OAuth)
docker exec "${CONTAINER_NAME}" find /app/backend -type f \( -name "*.py" -o -name "*.html" \) \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*oauth*" ! -name "*oidc*" ! -name "*auth*" ! -name "*login*" \
! -path "*/utils/oauth*" ! -path "*/utils/auth*" \
! -path "*/open_webui/utils/oauth*" ! -path "*/open_webui/utils/auth*" \
! -path "*/open_webui/main.py" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Powered by\|powered by" "$file" 2>/dev/null; then
echo " Удаление футера из: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
fi
done
echo ""
echo "✓ Бэкенд файлы обработаны (телеметрия отключена)"
echo "✓ OAuth/Authentik файлы защищены"
echo "✓ Фронтенд файлы обработаны"
echo ""
echo "8. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Не удалось перезапустить контейнер автоматически."
echo "Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== ПОЛНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Проверьте отсутствие упоминаний 'Open WebUI'"
echo " 3. Проверьте OAuth - должен работать нормально"
echo " 4. Проверьте отсутствие телеметрии (DevTools → Network)"
echo ""
echo "Если OAuth не работает, пересоздайте контейнер:"
echo " sudo docker compose stop open-webui"
echo " sudo docker compose rm -f open-webui"
echo " sudo docker compose up -d open-webui"

134
scripts/rebrand_fast.sh Executable file
View File

@@ -0,0 +1,134 @@
#!/bin/bash
# БЫСТРЫЙ ребрендинг - оптимизированная версия
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== БЫСТРЫЙ ребрендинг Open WebUI для iiEasy ==="
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
)
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
echo "2. БЫСТРОЕ удаление '(Open WebUI)' - поиск только в текстовых файлах..."
# ОПТИМИЗАЦИЯ: Сначала находим файлы с текстом через grep -l (быстро)
# Обрабатываем только нужные типы файлов
FILES=$(docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.json" -o -name "*.css" -o -name "*.mjs" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -lE "(Open WebUI)|\(Open WebUI\)|iiEasyWeb.*Open.*WebUI" {} \; 2>/dev/null)
if [ -z "$FILES" ]; then
echo " Файлов с '(Open WebUI)' не найдено"
else
COUNT=$(echo "$FILES" | wc -l)
echo " Найдено файлов: $COUNT"
echo "$FILES" | while read file; do
if [ -n "$file" ]; then
# Один sed с несколькими командами - быстрее
docker exec "${CONTAINER_NAME}" sed -i \
-e 's/(Open WebUI)//g' \
-e 's/\(Open WebUI\)//g' \
-e 's/ (Open WebUI)//g' \
-e 's/ \(Open WebUI\)//g' \
-e 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' \
-e 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' \
-e 's/iiEasyWeb(Open WebUI)/iiEasyWeb/g' \
-e "s/'(Open WebUI)'//g" \
-e 's/"(Open WebUI)"//g' \
-e 's/`(Open WebUI)`//g' \
-e 's/Войти в iiEasyWeb (Open WebUI)/Войти в iiEasyWeb/g' \
"$file" 2>/dev/null || true
fi
done
echo " Обработка завершена"
fi
echo "3. Замена ссылок на документацию..."
DOC_FILES=$(docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.json" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -lE "docs\.openwebui\.com|open-webui\.com/docs|github\.com/open-webui/docs" {} \; 2>/dev/null)
if [ -z "$DOC_FILES" ]; then
echo " Файлов со ссылками не найдено"
else
echo "$DOC_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i \
-e 's|https://docs.openwebui.com|https://note.iieasy.ru|g' \
-e 's|https://open-webui.com/docs|https://note.iieasy.ru|g' \
-e 's|https://github.com/open-webui/docs|https://note.iieasy.ru|g' \
-e 's|docs\.openwebui\.com|note.iieasy.ru|g' \
-e 's|open-webui\.com/docs|note.iieasy.ru|g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "4. Удаление социальных сетей и лицензии..."
SOCIAL_FILES=$(docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -lE "discord|twitter|x\.com|Github Repo|лицензионный|License" {} \; 2>/dev/null)
if [ -z "$SOCIAL_FILES" ]; then
echo " Файлов с соцсетями не найдено"
else
echo "$SOCIAL_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i \
-e '/discord\.gg/d' -e '/discord\.com/d' -e '/Discord/d' \
-e '/twitter\.com/d' -e '/x\.com/d' -e '/X (formerly Twitter)/d' -e '/Twitter/d' -e '/Follow/d' \
-e '/Github Repo/d' -e '/GitHub Repo/d' \
-e '/лицензионный тарифный план/d' -e '/Перейдите на лицензионный/d' \
-e '/расширенные возможности/d' -e '/настраиваемую тематику/d' \
-e '/фирменный стиль/d' -e '/специальную поддержку/d' -e '/Лицензия/d' \
"$file" 2>/dev/null || true
fi
done
fi
echo ""
echo "5. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== БЫСТРЫЙ ребрендинг завершен! ==="
echo ""
echo "Очистите кеш браузера (Ctrl+Shift+Delete)"

212
scripts/rebrand_final.sh Executable file
View File

@@ -0,0 +1,212 @@
#!/bin/bash
# ФИНАЛЬНЫЙ ребрендинг - удаляет ВСЕ упоминания и меняет ссылки на документацию
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== ФИНАЛЬНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "✓ Удаление ВСЕХ упоминаний '(Open WebUI)'"
echo "✓ Замена ссылок на документацию на note.iieasy.ru"
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
)
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
# Заменяем все существующие логотипы
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ] && [[ ! "$logo_file" == *"node_modules"* ]]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
echo "2. АГРЕССИВНОЕ удаление '(Open WebUI)' из ВСЕХ файлов..."
# Ищем ВО ВСЕХ файлах, включая бинарные (может быть в строковых константах)
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*.pyc" ! -name "*.pyo" ! -name "*.so" \
2>/dev/null | while read file; do
# Проверяем, это текстовый файл
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "(Open WebUI)|\(Open WebUI\)|iiEasyWeb.*Open.*WebUI" "$file" 2>/dev/null; then
echo " Удаление из: $file"
# Все возможные варианты
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ (Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ \(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb(Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i "s/'(Open WebUI)'//g" "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/"(Open WebUI)"//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/`(Open WebUI)`//g' "$file" 2>/dev/null || true
# Удаляем если в составе строки
docker exec "${CONTAINER_NAME}" sed -i 's/Войти в iiEasyWeb (Open WebUI)/Войти в iiEasyWeb/g' "$file" 2>/dev/null || true
fi
fi
done
echo "3. Замена ссылок на документацию на note.iieasy.ru..."
# Заменяем ссылки на документацию
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "docs\.openwebui\.com|open-webui\.com/docs|github\.com/open-webui/docs" "$file" 2>/dev/null; then
echo " Замена ссылок на документацию в: $file"
docker exec "${CONTAINER_NAME}" sed -i 's|https://docs.openwebui.com|https://note.iieasy.ru|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|https://open-webui.com/docs|https://note.iieasy.ru|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|https://github.com/open-webui/docs|https://note.iieasy.ru|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|docs\.openwebui\.com|note.iieasy.ru|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|open-webui\.com/docs|note.iieasy.ru|g' "$file" 2>/dev/null || true
fi
fi
done
echo "4. Замена 'Open WebUI' на 'iiEasyWeb' в тексте..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI" "$file" 2>/dev/null; then
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
fi
fi
done
echo "5. Проверка базы данных..."
# Пытаемся найти и исправить в базе данных
DB_PATH="/app/backend/data/webui.db"
if docker exec "${CONTAINER_NAME}" test -f "$DB_PATH" 2>/dev/null; then
echo " Найдена база данных, проверяем..."
if docker exec "${CONTAINER_NAME}" command -v sqlite3 >/dev/null 2>&1; then
# Ищем таблицы с текстовыми полями
TABLES=$(docker exec "${CONTAINER_NAME}" sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table';" 2>/dev/null)
echo "$TABLES" | while read table; do
if [ -n "$table" ]; then
# Пытаемся найти и заменить в текстовых полях
docker exec "${CONTAINER_NAME}" sqlite3 "$DB_PATH" "UPDATE $table SET value = REPLACE(value, '(Open WebUI)', '') WHERE value LIKE '%(Open WebUI)%';" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sqlite3 "$DB_PATH" "UPDATE $table SET value = REPLACE(value, 'Open WebUI', 'iiEasyWeb') WHERE value LIKE '%Open WebUI%';" 2>/dev/null || true
fi
done
fi
fi
echo "6. Удаление социальных сетей, GitHub и лицензии из футера..."
# Удаляем Discord
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "discord\.gg|discord\.com|Discord" "$file" 2>/dev/null; then
docker exec "${CONTAINER_NAME}" sed -i '/discord\.gg/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/discord\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Discord/d' "$file" 2>/dev/null || true
fi
fi
done
# Удаляем Twitter/X
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "twitter\.com|x\.com|X \(formerly Twitter\)|Twitter|Follow" "$file" 2>/dev/null; then
docker exec "${CONTAINER_NAME}" sed -i '/twitter\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/x\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/X (formerly Twitter)/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Twitter/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Follow/d' "$file" 2>/dev/null || true
fi
fi
done
# Удаляем GitHub Repo
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "Github Repo|GitHub Repo" "$file" 2>/dev/null; then
docker exec "${CONTAINER_NAME}" sed -i '/Github Repo/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/GitHub Repo/d' "$file" 2>/dev/null || true
fi
fi
done
# Удаляем лицензию
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "лицензионный тарифный план|Перейдите на лицензионный|Лицензия" "$file" 2>/dev/null; then
docker exec "${CONTAINER_NAME}" sed -i '/лицензионный тарифный план/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Перейдите на лицензионный/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/расширенные возможности/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/настраиваемую тематику/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/фирменный стиль/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/специальную поддержку/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Лицензия/d' "$file" 2>/dev/null || true
fi
fi
done
echo ""
echo "7. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== ФИНАЛЬНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Должно быть 'Войти в iiEasyWeb' (без '(Open WebUI)')"
echo " 3. Ссылки на документацию должны вести на note.iieasy.ru"
echo ""
echo "ВАЖНО: Очистите кеш браузера (Ctrl+Shift+Delete)"
echo ""
echo "Если '(Open WebUI)' все еще видно, проверьте через Admin Panel:"
echo " Settings → Appearance → Site Title"

209
scripts/rebrand_full.sh Executable file
View File

@@ -0,0 +1,209 @@
#!/bin/bash
# ПОЛНЫЙ ребрендинг Open WebUI для iiEasy
# Удаляет ВСЕ упоминания Open WebUI из интерфейса, но защищает OAuth
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== ПОЛНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "⚠ Удаление ВСЕХ упоминаний Open WebUI из интерфейса"
echo "⚠ OAuth/Authentik файлы защищены"
echo ""
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден. Запустите docker-compose up -d сначала."
exit 1
fi
# Проверка, что контейнер запущен
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен. Запустите docker-compose up -d."
exit 1
fi
echo "1. Замена логотипов и favicon..."
# Определяем пути для статических файлов
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
"/app/static"
"/app/public"
)
STATIC_DIR=""
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
STATIC_DIR="$dir"
echo " Найдена директория: $STATIC_DIR"
break
fi
done
if [ -z "$STATIC_DIR" ]; then
FAVICON_PATH=$(docker exec "${CONTAINER_NAME}" find /app -name "favicon.png" -o -name "favicon.ico" 2>/dev/null | head -1)
if [ -n "$FAVICON_PATH" ]; then
STATIC_DIR=$(dirname "$FAVICON_PATH")
else
STATIC_DIR="/app/web/build/_app/immutable"
docker exec "${CONTAINER_NAME}" mkdir -p "$STATIC_DIR" 2>/dev/null || true
fi
fi
# Копирование логотипов
for target_dir in "$STATIC_DIR" "/app/web/build/_app/immutable" "/app/web/static" "/app/web/build"; do
if docker exec "${CONTAINER_NAME}" test -d "$target_dir" 2>/dev/null || [ "$target_dir" = "$STATIC_DIR" ]; then
echo " Копирование в $target_dir..."
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${target_dir}/logo-dark.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.ico" ]; then
docker cp "$MEDIA_DIR/favicon.ico" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon-96x96.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.svg" ]; then
docker cp "$MEDIA_DIR/favicon.svg" "${CONTAINER_NAME}:${target_dir}/favicon.svg" 2>/dev/null || true
fi
fi
done
# Замена существующих favicon и logo
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" \) 2>/dev/null | head -10)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | head -10)
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
done
fi
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
# Копируем в public директории
PUBLIC_DIRS=("/app/web/public" "/app/public" "/app/backend/public")
for pub_dir in "${PUBLIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$pub_dir" 2>/dev/null; then
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${pub_dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.ico" 2>/dev/null || true
fi
break
fi
done
echo "2. Удаление упоминаний 'Open WebUI' из фронтенда (HTML/JS/TSX/Svelte)..."
# КРИТИЧНО: Изменяем ТОЛЬКО фронтенд файлы (веб-интерфейс)
# НЕ трогаем Python бэкенд файлы вообще, кроме исключений для безопасности
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.svelte" -o -name "*.json" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
# Проверяем, содержит ли файл упоминания Open WebUI
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI\|open-webui\|openwebui\|\(Open WebUI\)" "$file" 2>/dev/null; then
echo " Обработка фронтенд: $file"
# Замена "Open WebUI" на "iiEasyWeb"
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
# Удаление "(Open WebUI)" в скобках
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
# Замена "iiEasyWeb (Open WebUI)" на "iiEasyWeb"
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' "$file" 2>/dev/null || true
# Удаление "open-webui" и "openwebui" в тексте (но не в URL - они обычно в кавычках или переменных)
docker exec "${CONTAINER_NAME}" sed -i 's/open-webui/iieasyweb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/openwebui/iieasyweb/g' "$file" 2>/dev/null || true
fi
done
echo "3. Удаление упоминаний из статических JSON файлов конфигурации..."
# Изменяем только JSON файлы конфигурации фронтенда (не бэкенд)
docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.json" \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI\|open-webui\|openwebui" "$file" 2>/dev/null; then
echo " Обработка JSON: $file"
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/open-webui/iieasyweb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/openwebui/iieasyweb/g' "$file" 2>/dev/null || true
fi
done
echo "4. Удаление 'Powered by' футеров из фронтенда..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Powered by\|powered by" "$file" 2>/dev/null; then
echo " Удаление футера из: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*[Oo]pen.*[Ww]eb[Uu][Ii]/d' "$file" 2>/dev/null || true
fi
done
echo "5. Отключение проверки обновлений (только фронтенд)..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
-exec grep -l "github.com.*releases\|check.*update\|update.*check" {} \; 2>/dev/null | while read file; do
echo " Отключение проверки обновлений в: $file"
docker exec "${CONTAINER_NAME}" sed -i 's|https://api.github.com/repos/open-webui|# https://api.github.com/repos/open-webui|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|github.com/open-webui|# github.com/open-webui|g' "$file" 2>/dev/null || true
done
echo ""
echo "⚠ ВАЖНО: Python бэкенд файлы НЕ изменялись"
echo "⚠ OAuth/Authentik файлы защищены"
echo "⚠ Изменены только фронтенд файлы (веб-интерфейс)"
echo ""
echo "6. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Не удалось перезапустить контейнер автоматически."
echo "Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== ПОЛНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Проверьте отсутствие упоминаний 'Open WebUI'"
echo " 3. Проверьте OAuth - должен работать нормально"
echo ""
echo "Если OAuth не работает, пересоздайте контейнер:"
echo " sudo docker compose stop open-webui"
echo " sudo docker compose rm -f open-webui"
echo " sudo docker compose up -d open-webui"

173
scripts/rebrand_precise.sh Executable file
View File

@@ -0,0 +1,173 @@
#!/bin/bash
# ТОЧНЫЙ ребрендинг Open WebUI для iiEasy
# Находит и удаляет ВСЕ упоминания "(Open WebUI)" и "Open WebUI"
# Только безопасные замены в текстовом контенте
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== ТОЧНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "✓ Поиск и удаление ВСЕХ упоминаний '(Open WebUI)'"
echo "✓ Замена 'Open WebUI' на 'iiEasyWeb'"
echo "✓ Исправление логотипов"
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов и favicon..."
# Находим все места, где могут быть логотипы
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
)
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
echo " Копирование в $dir..."
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
# Заменяем существующие логотипы везде
echo " Поиск и замена существующих логотипов..."
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" -o -name "logo.ico" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ] && [[ ! "$logo_file" == *"node_modules"* ]]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ] && [[ ! "$favicon_file" == *"node_modules"* ]]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
fi
done
fi
echo "2. Поиск и удаление '(Open WebUI)' из ВСЕХ файлов..."
# Ищем ВСЕ файлы с упоминанием "(Open WebUI)" - включая скомпилированные
# Ищем в разных вариантах написания
docker exec "${CONTAINER_NAME}" find /app -type f \( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -o -name "*.json" -o -name "*.css" -o -name "*.mjs" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
# Проверяем разные варианты написания - включая с пробелами и без
if docker exec "${CONTAINER_NAME}" grep -qE "(Open WebUI)|\(Open WebUI\)|iiEasyWeb \(Open WebUI\)|iiEasyWeb\(Open WebUI\)" "$file" 2>/dev/null; then
echo " Удаление '(Open WebUI)' из: $file"
# Удаляем различные варианты написания в скобках
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ (Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/ \(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb \(Open WebUI\)/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb(Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
# Также удаляем если есть пробелы вокруг
docker exec "${CONTAINER_NAME}" sed -i 's/\s*(Open WebUI)\s*//g' "$file" 2>/dev/null || true
# Удаляем если текст в кавычках или переменных
docker exec "${CONTAINER_NAME}" sed -i "s/'(Open WebUI)'//g" "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/"(Open WebUI)"//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/`(Open WebUI)`//g' "$file" 2>/dev/null || true
fi
done
echo "3. Замена 'Open WebUI' на 'iiEasyWeb' в тексте..."
# Заменяем "Open WebUI" на "iiEasyWeb" в текстовом контенте
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Open WebUI" "$file" 2>/dev/null; then
echo " Замена в: $file"
# Заменяем только в текстовом контенте, не в коде
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
fi
done
echo "4. Удаление 'Powered by Open WebUI'..."
docker exec "${CONTAINER_NAME}" find /app -type f \( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" grep -q "Powered by.*Open WebUI\|powered by.*Open WebUI" "$file" 2>/dev/null; then
echo " Удаление футера из: $file"
docker exec "${CONTAINER_NAME}" sed -i '/Powered by.*Open WebUI/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/powered by.*Open WebUI/d' "$file" 2>/dev/null || true
fi
done
echo "5. Поиск упоминаний в скомпилированных файлах (включая минифицированные)..."
# Ищем в скомпилированных JS файлах (могут быть минифицированы)
# Также ищем в build директориях
docker exec "${CONTAINER_NAME}" find /app/web/build -type f \( -name "*.js" -o -name "*.mjs" \) \
! -path "*/node_modules/*" \
2>/dev/null | while read file; do
# Ищем разные варианты, включая минифицированные (без пробелов)
if docker exec "${CONTAINER_NAME}" grep -qE "Open WebUI|\(Open WebUI\)|iiEasyWeb \(Open WebUI\)|OpenWebUI" "$file" 2>/dev/null; then
echo " Обработка скомпилированного: $file"
docker exec "${CONTAINER_NAME}" sed -i 's/Open WebUI/iiEasyWeb/g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/(Open WebUI)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/\(Open WebUI\)//g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' "$file" 2>/dev/null || true
fi
done
echo "6. Поиск в базе данных (если текст там хранится)..."
# Проверяем, может ли текст быть в базе данных
# Если есть SQLite база, можем попробовать заменить там
DB_PATH="/app/backend/data/webui.db"
if docker exec "${CONTAINER_NAME}" test -f "$DB_PATH" 2>/dev/null; then
echo " Найдена база данных, проверяем наличие '(Open WebUI)'..."
# Ищем в базе через sqlite3 (если доступен)
if docker exec "${CONTAINER_NAME}" command -v sqlite3 >/dev/null 2>&1; then
# Ищем в текстовых полях базы
docker exec "${CONTAINER_NAME}" sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table';" 2>/dev/null | while read table; do
if [ -n "$table" ]; then
# Пытаемся найти и заменить в текстовых полях (осторожно!)
echo " Проверка таблицы: $table"
fi
done
fi
fi
echo ""
echo "6. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== ТОЧНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Должно быть 'Войти в iiEasyWeb' (без '(Open WebUI)')"
echo " 3. Логотип должен отображаться правильно"
echo ""
echo "Если '(Open WebUI)' все еще видно, очистите кеш браузера (Ctrl+Shift+Delete)"

152
scripts/rebrand_safe.sh Executable file
View File

@@ -0,0 +1,152 @@
#!/bin/bash
# БЕЗОПАСНЫЙ скрипт ребрендинга Open WebUI для iiEasy
# Только логотипы и favicon, БЕЗ изменения кода Python/JS
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== БЕЗОПАСНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "⚠ ВНИМАНИЕ: Этот скрипт изменяет ТОЛЬКО логотипы и favicon"
echo "⚠ Код Python/JS НЕ изменяется для защиты OAuth/Authentik"
echo ""
# Проверка наличия контейнера
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не найден. Запустите docker-compose up -d сначала."
exit 1
fi
# Проверка, что контейнер запущен
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен. Запустите docker-compose up -d."
exit 1
fi
echo "1. Замена логотипов и favicon..."
# Определяем пути для статических файлов в Open WebUI
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
"/app/static"
"/app/public"
)
# Находим существующую директорию со статическими файлами
STATIC_DIR=""
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
STATIC_DIR="$dir"
echo " Найдена директория статических файлов: $STATIC_DIR"
break
fi
done
if [ -z "$STATIC_DIR" ]; then
echo " Предупреждение: Директория статических файлов не найдена, пробуем найти через поиск favicon..."
FAVICON_PATH=$(docker exec "${CONTAINER_NAME}" find /app -name "favicon.png" -o -name "favicon.ico" 2>/dev/null | head -1)
if [ -n "$FAVICON_PATH" ]; then
STATIC_DIR=$(dirname "$FAVICON_PATH")
echo " Найдена директория через поиск favicon: $STATIC_DIR"
else
STATIC_DIR="/app/web/build/_app/immutable"
echo " Используем стандартный путь: $STATIC_DIR"
docker exec "${CONTAINER_NAME}" mkdir -p "$STATIC_DIR" 2>/dev/null || true
fi
fi
# Копирование логотипов (приоритет: PNG > SVG)
for target_dir in "$STATIC_DIR" "/app/web/build/_app/immutable" "/app/web/static" "/app/web/build"; do
if docker exec "${CONTAINER_NAME}" test -d "$target_dir" 2>/dev/null || [ "$target_dir" = "$STATIC_DIR" ]; then
echo " Копирование в $target_dir..."
# Логотипы
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${target_dir}/logo.svg" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${target_dir}/logo-dark.svg" 2>/dev/null || true
fi
# Favicon
if [ -f "$MEDIA_DIR/favicon.ico" ]; then
docker cp "$MEDIA_DIR/favicon.ico" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon.ico" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${target_dir}/favicon-96x96.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/favicon.svg" ]; then
docker cp "$MEDIA_DIR/favicon.svg" "${CONTAINER_NAME}:${target_dir}/favicon.svg" 2>/dev/null || true
fi
fi
done
# Поиск и замена существующих favicon и logo файлов
echo " Поиск существующих favicon и logo файлов для замены..."
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" \) 2>/dev/null | head -10)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" \) 2>/dev/null | head -10)
# Заменяем существующие favicon файлы
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ]; then
echo " Замена: $favicon_file"
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
done
fi
# Заменяем существующие logo файлы
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ]; then
echo " Замена: $logo_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
done
fi
# Копируем в public директории
PUBLIC_DIRS=(
"/app/web/public"
"/app/public"
"/app/backend/public"
)
for pub_dir in "${PUBLIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$pub_dir" 2>/dev/null; then
echo " Копирование в $pub_dir..."
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${pub_dir}/logo.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${pub_dir}/favicon.ico" 2>/dev/null || true
fi
break
fi
done
echo ""
echo "=== БЕЗОПАСНЫЙ ребрендинг завершен! ==="
echo ""
echo "⚠ Изменены ТОЛЬКО логотипы и favicon"
echo "⚠ Код Python/JS НЕ изменялся - OAuth/Authentik защищены"
echo ""
echo "Рекомендуется использовать Admin Panel для постоянных изменений:"
echo " Settings → Appearance → Logo (загрузите файлы из /app/media/)"
echo ""
echo "Если нужно изменить текст интерфейса, используйте Admin Panel или"
echo "настройте переменные окружения в docker-compose.yml"

460
scripts/rebrand_safe_final.sh Executable file
View File

@@ -0,0 +1,460 @@
#!/bin/bash
# БЕЗОПАСНЫЙ финальный ребрендинг - не ломает функциональность
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== БЕЗОПАСНЫЙ финальный ребрендинг Open WebUI для iiEasy ==="
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов, splash.png и favicon..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
"/app/backend/static"
"/app/static"
"/app/web/public"
"/app/public"
)
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
# Основной логотип
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash.png" 2>/dev/null || true
# Также создаем splash-dark.png для темной темы
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash-dark.png" 2>/dev/null || true
fi
# Логотип для светлой темы
if [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${dir}/logo-light.svg" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${dir}/logo.svg" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash-light.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo.png" ]; then
# Если нет SVG, используем PNG для светлой темы
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo-light.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash-light.png" 2>/dev/null || true
fi
# Логотип для темной темы
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${dir}/logo-dark.svg" 2>/dev/null || true
# Для splash-dark.png используем PNG версию (если есть logo-dark.png) или обычный logo.png
if [ -f "$MEDIA_DIR/logo-dark.png" ]; then
docker cp "$MEDIA_DIR/logo-dark.png" "${CONTAINER_NAME}:${dir}/splash-dark.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash-dark.png" 2>/dev/null || true
fi
elif [ -f "$MEDIA_DIR/logo.png" ]; then
# Если нет темного SVG, используем PNG для темной темы
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo-dark.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash-dark.png" 2>/dev/null || true
fi
# Favicon
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
# Также создаем favicon-dark.png и favicon-light.png
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon-dark.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon-light.png" 2>/dev/null || true
# Apple touch icon для iOS
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/apple-touch-icon.png" 2>/dev/null || true
elif [ -f "$MEDIA_DIR/logo.png" ]; then
# Если нет отдельного favicon, используем logo.png
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/favicon-dark.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/favicon-light.png" 2>/dev/null || true
# Apple touch icon для iOS
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/apple-touch-icon.png" 2>/dev/null || true
fi
fi
done
# Заменяем ВСЕ существующие favicon файлы (включая favicon.ico, favicon-dark.png, favicon-light.png, apple-touch-icon.png)
echo " Замена всех favicon файлов..."
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "favicon.png" -o -name "favicon.ico" -o -name "favicon.svg" -o -name "favicon-dark.png" -o -name "favicon-light.png" -o -name "apple-touch-icon.png" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/favicon.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ] && [[ ! "$favicon_file" == *"node_modules"* ]]; then
favicon_name=$(basename "$favicon_file")
echo " Замена favicon: $favicon_file"
# Для темной темы используем logo-dark если есть, иначе favicon.png
if [[ "$favicon_name" == *"dark"* ]]; then
if [ -f "$MEDIA_DIR/logo-dark.svg" ] || [ -f "$MEDIA_DIR/logo-dark.png" ]; then
# Используем logo.png для favicon-dark (так как favicon должен быть PNG)
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
else
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
fi
# Для светлой темы
elif [[ "$favicon_name" == *"light"* ]]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
# Apple touch icon или обычный favicon
else
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
# Также создаем .ico версию в той же директории для обычных favicon
if [[ "$favicon_name" == "favicon.png" ]]; then
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
fi
fi
done
elif [ -f "$MEDIA_DIR/logo.png" ]; then
# Если нет favicon.png, используем logo.png
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ] && [[ ! "$favicon_file" == *"node_modules"* ]]; then
favicon_name=$(basename "$favicon_file")
echo " Замена favicon: $favicon_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
# Также создаем .ico версию для обычных favicon (не для dark/light/apple-touch-icon)
if [[ "$favicon_name" == "favicon.png" ]]; then
favicon_dir=$(dirname "$favicon_file")
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${favicon_dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
fi
# Заменяем все существующие splash.png и splash-dark.png
EXISTING_SPLASH=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "splash.png" -o -name "splash-dark.png" -o -name "splash-light.png" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_SPLASH" | while read -r splash_file; do
if [ -n "$splash_file" ] && [[ ! "$splash_file" == *"node_modules"* ]]; then
splash_name=$(basename "$splash_file")
# Для темной темы используем logo-dark если есть, иначе обычный logo
if [[ "$splash_name" == *"dark"* ]]; then
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
# Конвертируем SVG в PNG или используем logo.png
echo " Замена splash-dark.png: $splash_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
else
echo " Замена splash-dark.png: $splash_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
fi
# Для светлой темы
elif [[ "$splash_name" == *"light"* ]]; then
if [ -f "$MEDIA_DIR/logo-light.svg" ]; then
echo " Замена splash-light.png: $splash_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
else
echo " Замена splash-light.png: $splash_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
fi
# Обычный splash
else
echo " Замена splash.png: $splash_file"
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
fi
fi
done
fi
# Заменяем все существующие logo файлы (включая logo-dark и logo-light)
EXISTING_LOGOS=$(docker exec "${CONTAINER_NAME}" find /app -type f \( -name "logo.png" -o -name "logo.svg" -o -name "logo-light.*" -o -name "logo-dark.*" \) 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_LOGOS" | while read -r logo_file; do
if [ -n "$logo_file" ] && [[ ! "$logo_file" == *"node_modules"* ]]; then
logo_name=$(basename "$logo_file")
# Для темной темы используем logo-dark если есть, иначе обычный logo
if [[ "$logo_name" == *"dark"* ]]; then
if [ -f "$MEDIA_DIR/logo-dark.svg" ]; then
docker cp "$MEDIA_DIR/logo-dark.svg" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
else
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
# Для светлой темы используем logo-light если есть
elif [[ "$logo_name" == *"light"* ]]; then
if [ -f "$MEDIA_DIR/logo-light.svg" ]; then
docker cp "$MEDIA_DIR/logo-light.svg" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
else
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
# Обычный логотип
else
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${logo_file}" 2>/dev/null || true
fi
fi
done
fi
echo "2. БЕЗОПАСНОЕ удаление '(Open WebUI)' из HTML/Svelte и Python шаблонов..."
# HTML, Svelte и Python файлы (шаблоны)
FILES=$(docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.py" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
! -name "*test*" ! -name "*__pycache__*" \
-exec grep -lE "(Open WebUI)|\(Open WebUI\)" {} \; 2>/dev/null)
if [ -z "$FILES" ]; then
echo " Файлов с '(Open WebUI)' не найдено"
else
COUNT=$(echo "$FILES" | wc -l)
echo " Найдено файлов: $COUNT"
echo "$FILES" | while read file; do
if [ -n "$file" ]; then
# Безопасная замена только в HTML/Svelte
docker exec "${CONTAINER_NAME}" sed -i \
-e 's/(Open WebUI)//g' \
-e 's/\(Open WebUI\)//g' \
-e 's/ (Open WebUI)//g' \
-e 's/ \(Open WebUI\)//g' \
-e 's/iiEasyWeb (Open WebUI)/iiEasyWeb/g' \
-e 's/Войти в iiEasyWeb (Open WebUI)/Войти в iiEasyWeb/g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "3. Замена ссылок на документацию (только в HTML/Svelte)..."
DOC_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "docs\.openwebui\.com|open-webui\.com/docs" {} \; 2>/dev/null)
if [ -z "$DOC_FILES" ]; then
echo " Файлов со ссылками не найдено"
else
echo "$DOC_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i \
-e 's|https://docs.openwebui.com|https://note.iieasy.ru|g' \
-e 's|https://open-webui.com/docs|https://note.iieasy.ru|g' \
-e 's|docs\.openwebui\.com|note.iieasy.ru|g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "4. Исправление favicon.ico, favicon.png, favicon-dark.png и apple-touch-icon.png в HTML/Svelte шаблонах..."
# Заменяем ссылки на favicon.ico, favicon.png, favicon-dark.png и apple-touch-icon.png на наш логотип
TEMPLATE_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "/static/favicon(-dark|-light)?\.(png|ico)|favicon(-dark|-light)?\.(ico|png)|apple-touch-icon\.png|rel=\"(shortcut )?icon\"|rel=\"apple-touch-icon\"" {} \; 2>/dev/null)
if [ -n "$TEMPLATE_FILES" ]; then
echo "$TEMPLATE_FILES" | while read file; do
if [ -n "$file" ]; then
# Заменяем favicon.ico, favicon.png, favicon-dark.png и apple-touch-icon.png на logo.png в ссылках
docker exec "${CONTAINER_NAME}" sed -i \
-e 's|/static/favicon-dark\.png|/static/logo.png|g' \
-e 's|/static/favicon-light\.png|/static/logo.png|g' \
-e 's|/static/favicon\.ico|/static/logo.png|g' \
-e 's|/static/favicon\.png|/static/logo.png|g' \
-e 's|/static/apple-touch-icon\.png|/static/logo.png|g' \
-e 's|src="/static/favicon-dark\.png"|src="/static/logo.png"|g' \
-e 's|src="/static/favicon\.png"|src="/static/logo.png"|g' \
-e 's|src="/static/apple-touch-icon\.png"|src="/static/logo.png"|g' \
-e 's|href="[^"]*favicon-dark\.png"|href="/static/logo.png"|g' \
-e 's|href="[^"]*favicon\.ico"|href="/static/logo.png"|g' \
-e 's|href="[^"]*favicon\.png"|href="/static/logo.png"|g' \
-e 's|href="[^"]*apple-touch-icon\.png"|href="/static/logo.png"|g' \
-e 's|href="https://odo\.iieasy\.ru/static/favicon\.ico"|href="/static/logo.png"|g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "4.1. Исправление splash-dark.png, favicon-dark.png и логотипов в окне авторизации..."
# Ищем файлы, где используется splash-dark.png, favicon-dark.png или логотип в окне авторизации
AUTH_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "splash-dark|splash-dark\.png|favicon-dark\.png|auth.*logo|login.*logo|dark.*splash|dark.*favicon" {} \; 2>/dev/null)
if [ -n "$AUTH_FILES" ]; then
echo "$AUTH_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Исправление логотипа в окне авторизации: $file"
# Заменяем splash-dark.png и favicon-dark.png на наш логотип
docker exec "${CONTAINER_NAME}" sed -i \
-e 's|/static/splash-dark\.png|/static/logo.png|g' \
-e 's|/static/favicon-dark\.png|/static/logo.png|g' \
-e 's|splash-dark\.png|logo.png|g' \
-e 's|favicon-dark\.png|logo.png|g' \
-e 's|src="/static/favicon-dark\.png"|src="/static/logo.png"|g' \
-e 's|src="[^"]*splash-dark[^"]*"|src="/static/logo.png"|g' \
-e 's|src="[^"]*favicon-dark[^"]*"|src="/static/logo.png"|g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "5. Исправление API endpoint для изображения профиля модели..."
# Ищем и заменяем API endpoint для изображения профиля модели
API_FILES=$(docker exec "${CONTAINER_NAME}" find /app -type f \
\( -name "*.html" -o -name "*.svelte" -o -name "*.js" -o -name "*.ts" -o -name "*.py" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "model/profile/image\|models.*profile.*image" {} \; 2>/dev/null)
if [ -n "$API_FILES" ]; then
echo "$API_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Исправление API endpoint в: $file"
# Заменяем API endpoint на статический логотип
docker exec "${CONTAINER_NAME}" sed -i 's|/api/v1/models/model/profile/image|/static/logo.png|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|api/v1/models/model/profile/image|static/logo.png|g' "$file" 2>/dev/null || true
fi
done
fi
# Также ищем в Python коде, который генерирует этот endpoint
PYTHON_API=$(docker exec "${CONTAINER_NAME}" find /app/backend -type f -name "*.py" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
-exec grep -l "profile.*image\|model.*profile\|def.*profile" {} \; 2>/dev/null)
if [ -n "$PYTHON_API" ]; then
echo "$PYTHON_API" | while read file; do
if [ -n "$file" ]; then
# Ищем функции, которые возвращают изображение профиля и заменяем на статический логотип
echo " Проверка Python API в: $file"
# Это нужно делать более аккуратно - просто заменим возвращаемый путь
docker exec "${CONTAINER_NAME}" sed -i 's|/static/favicon.png|/static/logo.png|g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|favicon.png|logo.png|g' "$file" 2>/dev/null || true
fi
done
fi
echo "6. Удаление проверки обновлений и ссылок на GitHub (только Svelte файлы)..."
# Ищем ТОЛЬКО в исходных Svelte файлах - не трогаем скомпилированные JS
UPDATE_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.svelte" \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "Проверить обновления|Check for updates|github.com/open-webui/releases|последняя|latest" {} \; 2>/dev/null)
if [ -z "$UPDATE_FILES" ]; then
echo " Файлов с проверкой обновлений не найдено"
else
COUNT=$(echo "$UPDATE_FILES" | wc -l)
echo " Найдено Svelte файлов: $COUNT"
echo "$UPDATE_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Удаление проверки обновлений из: $file"
# Удаляем кнопку "Проверить обновления"
docker exec "${CONTAINER_NAME}" sed -i '/Проверить обновления/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Check for updates/d' "$file" 2>/dev/null || true
# Удаляем ссылку на GitHub releases с текстом "(последняя)"
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*href="https://github.com/open-webui/open-webui/releases/tag/[^"]*"[^>]*>(последняя)</a>||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|(последняя)||g' "$file" 2>/dev/null || true
# Удаляем "Посмотреть, что нового"
docker exec "${CONTAINER_NAME}" sed -i '/Посмотреть, что нового/d' "$file" 2>/dev/null || true
fi
done
fi
echo "7. Удаление социальных сетей, GitHub и блока 'Помощь' (только Svelte файлы)..."
# Ищем ТОЛЬКО в исходных Svelte файлах
SOCIAL_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.svelte" \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "discord|twitter|x\.com|Github Repo|github.com/open-webui|Помощь|Help|обратитесь за поддержкой" {} \; 2>/dev/null)
if [ -z "$SOCIAL_FILES" ]; then
echo " Файлов с соцсетями не найдено"
else
COUNT=$(echo "$SOCIAL_FILES" | wc -l)
echo " Найдено Svelte файлов: $COUNT"
echo "$SOCIAL_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Удаление соцсетей из: $file"
# Удаляем ссылки на Discord
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*href="https://discord.gg/[^"]*"[^>]*>.*</a>||g' "$file" 2>/dev/null || true
# Удаляем ссылки на Twitter/X
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*href="https://twitter.com/[^"]*"[^>]*>.*</a>||g' "$file" 2>/dev/null || true
# Удаляем ссылки на GitHub repo
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*href="https://github.com/open-webui/open-webui"[^>]*>.*</a>||g' "$file" 2>/dev/null || true
# Удаляем badges (img.shields.io)
docker exec "${CONTAINER_NAME}" sed -i 's|<img[^>]*shields.io[^>]*>||g' "$file" 2>/dev/null || true
# Удаляем текст блока "Помощь"
docker exec "${CONTAINER_NAME}" sed -i '/Узнайте, как использовать/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/обратитесь за поддержкой/d' "$file" 2>/dev/null || true
fi
done
fi
echo "8. Удаление блока 'Лицензия' полностью (только Svelte файлы)..."
# Ищем ТОЛЬКО в исходных Svelte файлах
LICENSE_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.svelte" \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "Лицензия|License|лицензионный тарифный план|Перейдите на лицензионный" {} \; 2>/dev/null)
if [ -z "$LICENSE_FILES" ]; then
echo " Файлов с лицензией не найдено"
else
COUNT=$(echo "$LICENSE_FILES" | wc -l)
echo " Найдено Svelte файлов: $COUNT"
echo "$LICENSE_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Удаление блока лицензии из: $file"
# Удаляем только текст блока лицензии
docker exec "${CONTAINER_NAME}" sed -i '/Перейдите на лицензионный/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/расширенные возможности/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/настраиваемую тематику/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/фирменный стиль/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/специальную поддержку/d' "$file" 2>/dev/null || true
fi
done
fi
echo "9. Добавление надписи 'Основано на Open WebUI' внизу настроек..."
# Ищем файлы настроек для добавления надписи
# Это сложнее сделать автоматически, поэтому просто отмечаем файлы
SETTINGS_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.svelte" \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -l "Settings\|Настройки\|General\|Общее" {} \; 2>/dev/null | head -3)
if [ -n "$SETTINGS_FILES" ]; then
echo " Найдены файлы настроек (надпись нужно добавить вручную):"
echo "$SETTINGS_FILES" | while read file; do
if [ -n "$file" ]; then
echo " - $file"
fi
done
echo ""
echo " Добавьте в конец блока настроек перед закрывающим тегом:"
echo " <div class='text-xs text-gray-400 dark:text-gray-500 mt-4 text-center'>"
echo " Основано на <span class='text-gray-500'>Open WebUI</span>"
echo " </div>"
fi
echo ""
echo "10. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== БЕЗОПАСНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. splash.png должен быть заменен на ваш логотип"
echo " 3. Проверка обновлений и ссылки на GitHub должны быть удалены"
echo " 4. Социальные сети и блок лицензии должны быть удалены"
echo " 5. Очистите кеш браузера (Ctrl+Shift+Delete)"
echo ""
echo "Примечание: Надпись 'Основано на Open WebUI' нужно добавить вручную"
echo "в файлах настроек (см. вывод выше) или через Admin Panel"

185
scripts/rebrand_ultra_safe.sh Executable file
View File

@@ -0,0 +1,185 @@
#!/bin/bash
# УЛЬТРА БЕЗОПАСНЫЙ ребрендинг - удаляет только конкретные блоки, не ломая структуру
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
MEDIA_DIR="$PROJECT_DIR/media"
CONTAINER_NAME="open-webui"
echo "=== УЛЬТРА БЕЗОПАСНЫЙ ребрендинг Open WebUI для iiEasy ==="
echo "⚠ Удаляет только конкретные HTML блоки, не трогает код"
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Замена логотипов..."
STATIC_DIRS=(
"/app/web/build/_app/immutable"
"/app/web/static"
"/app/web/build"
)
for dir in "${STATIC_DIRS[@]}"; do
if docker exec "${CONTAINER_NAME}" test -d "$dir" 2>/dev/null; then
if [ -f "$MEDIA_DIR/logo.png" ]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/logo.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${dir}/splash.png" 2>/dev/null || true
fi
if [ -f "$MEDIA_DIR/favicon.png" ]; then
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.png" 2>/dev/null || true
docker cp "$MEDIA_DIR/favicon.png" "${CONTAINER_NAME}:${dir}/favicon.ico" 2>/dev/null || true
fi
fi
done
# Заменяем существующие файлы
EXISTING_SPLASH=$(docker exec "${CONTAINER_NAME}" find /app -type f -name "splash.png" 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_SPLASH" | while read -r splash_file; do
if [ -n "$splash_file" ] && [[ ! "$splash_file" == *"node_modules"* ]]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${splash_file}" 2>/dev/null || true
fi
done
fi
EXISTING_FAVICONS=$(docker exec "${CONTAINER_NAME}" find /app -type f -name "favicon.png" 2>/dev/null)
if [ -f "$MEDIA_DIR/logo.png" ]; then
echo "$EXISTING_FAVICONS" | while read -r favicon_file; do
if [ -n "$favicon_file" ] && [[ ! "$favicon_file" == *"node_modules"* ]]; then
docker cp "$MEDIA_DIR/logo.png" "${CONTAINER_NAME}:${favicon_file}" 2>/dev/null || true
fi
done
fi
echo "2. Удаление '(Open WebUI)' из HTML/Svelte..."
FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "(Open WebUI)|\(Open WebUI\)" {} \; 2>/dev/null)
if [ -n "$FILES" ]; then
echo "$FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i \
-e 's/(Open WebUI)//g' \
-e 's/\(Open WebUI\)//g' \
-e 's/ (Open WebUI)//g' \
-e 's/Войти в iiEasyWeb (Open WebUI)/Войти в iiEasyWeb/g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "3. Замена ссылок на документацию..."
DOC_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -lE "docs\.openwebui\.com" {} \; 2>/dev/null)
if [ -n "$DOC_FILES" ]; then
echo "$DOC_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i \
-e 's|https://docs.openwebui.com|https://note.iieasy.ru|g' \
-e 's|docs\.openwebui\.com|note.iieasy.ru|g' \
"$file" 2>/dev/null || true
fi
done
fi
echo "4. Исправление favicon.png на logo.png..."
TEMPLATE_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -l "/static/favicon.png" {} \; 2>/dev/null)
if [ -n "$TEMPLATE_FILES" ]; then
echo "$TEMPLATE_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i 's|/static/favicon.png|/static/logo.png|g' "$file" 2>/dev/null || true
fi
done
fi
echo "5. Исправление API endpoint для изображения профиля модели..."
API_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f \
\( -name "*.html" -o -name "*.svelte" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -l "model/profile/image" {} \; 2>/dev/null)
if [ -n "$API_FILES" ]; then
echo "$API_FILES" | while read file; do
if [ -n "$file" ]; then
docker exec "${CONTAINER_NAME}" sed -i 's|/api/v1/models/model/profile/image|/static/logo.png|g' "$file" 2>/dev/null || true
fi
done
fi
echo "6. Удаление конкретных HTML блоков (безопасно)..."
# Ищем только Svelte файлы настроек
SETTINGS_FILES=$(docker exec "${CONTAINER_NAME}" find /app/web -type f -name "*.svelte" \
! -path "*/node_modules/*" ! -path "*/.next/*" \
-exec grep -l "Проверить обновления\|Помощь\|Лицензия\|Version\|Help\|License" {} \; 2>/dev/null)
if [ -n "$SETTINGS_FILES" ]; then
echo "$SETTINGS_FILES" | while read file; do
if [ -n "$file" ]; then
echo " Обработка файла настроек: $file"
# Удаляем блок проверки обновлений - ищем по уникальным классам и тексту
# Удаляем кнопку "Проверить обновления"
docker exec "${CONTAINER_NAME}" sed -i '/Проверить обновления/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Check for updates/d' "$file" 2>/dev/null || true
# Удаляем ссылку "(последняя)" с GitHub
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*github.com/open-webui/releases[^>]*>.*последняя.*</a>||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|(последняя)||g' "$file" 2>/dev/null || true
# Удаляем "Посмотреть, что нового"
docker exec "${CONTAINER_NAME}" sed -i '/Посмотреть, что нового/d' "$file" 2>/dev/null || true
# Удаляем весь блок "Помощь" - ищем по заголовку и удаляем до следующего блока
# Более безопасно - удаляем только содержимое блока
docker exec "${CONTAINER_NAME}" sed -i '/Узнайте, как использовать/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/обратитесь за поддержкой/d' "$file" 2>/dev/null || true
# Удаляем badges соцсетей - ищем по shields.io
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*discord.gg[^>]*>.*</a>||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*twitter.com[^>]*>.*</a>||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|<a[^>]*github.com/open-webui[^>]*>.*</a>||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|<img[^>]*shields.io[^>]*>||g' "$file" 2>/dev/null || true
# Удаляем блок "Лицензия"
docker exec "${CONTAINER_NAME}" sed -i '/Перейдите на лицензионный/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/расширенные возможности/d' "$file" 2>/dev/null || true
fi
done
fi
echo ""
echo "7. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== УЛЬТРА БЕЗОПАСНЫЙ ребрендинг завершен! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. Очистите кеш браузера (Ctrl+Shift+Delete)"
echo ""
echo "Примечание: Если блоки все еще видны, они могут быть в скомпилированных JS файлах."
echo "В этом случае нужно найти исходные Svelte файлы и удалить блоки там."

133
scripts/remove_footer_links.sh Executable file
View File

@@ -0,0 +1,133 @@
#!/bin/bash
# Удаление социальных сетей, GitHub и лицензии из футера
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
CONTAINER_NAME="open-webui"
echo "=== Удаление социальных сетей, GitHub и лицензии из футера ==="
echo ""
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Ошибка: Контейнер ${CONTAINER_NAME} не запущен."
exit 1
fi
echo "1. Удаление ссылок на Discord..."
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "discord\.gg|discord\.com|Discord" "$file" 2>/dev/null; then
echo " Удаление Discord из: $file"
# Удаляем строки с Discord
docker exec "${CONTAINER_NAME}" sed -i '/discord\.gg/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/discord\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Discord/d' "$file" 2>/dev/null || true
# Удаляем ссылки
docker exec "${CONTAINER_NAME}" sed -i 's|https://discord.gg/[^"]*||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|https://discord.com/[^"]*||g' "$file" 2>/dev/null || true
fi
fi
done
echo "2. Удаление ссылок на Twitter/X..."
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "twitter\.com|x\.com|X \(formerly Twitter\)|Twitter" "$file" 2>/dev/null; then
echo " Удаление Twitter/X из: $file"
# Удаляем строки с Twitter/X
docker exec "${CONTAINER_NAME}" sed -i '/twitter\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/x\.com/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/X (formerly Twitter)/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Twitter/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Follow/d' "$file" 2>/dev/null || true
# Удаляем ссылки
docker exec "${CONTAINER_NAME}" sed -i 's|https://twitter.com/[^"]*||g' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i 's|https://x.com/[^"]*||g' "$file" 2>/dev/null || true
fi
fi
done
echo "3. Удаление ссылок на GitHub Repo..."
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "github\.com/open-webui|Github Repo|GitHub" "$file" 2>/dev/null; then
echo " Удаление GitHub из: $file"
# Удаляем строки с GitHub
docker exec "${CONTAINER_NAME}" sed -i '/Github Repo/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/GitHub Repo/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/github\.com\/open-webui/d' "$file" 2>/dev/null || true
# Удаляем ссылки на GitHub repo (но не все GitHub ссылки, только repo)
docker exec "${CONTAINER_NAME}" sed -i 's|https://github.com/open-webui/[^"]*||g' "$file" 2>/dev/null || true
fi
fi
done
echo "4. Удаление строки про лицензию и тарифный план..."
docker exec "${CONTAINER_NAME}" find /app -type f \
! -path "*/node_modules/*" ! -path "*/.next/*" \
! -path "*/oauth*" ! -path "*/oidc*" ! -path "*authentik*" ! -path "*openid*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "лицензионный тарифный план|Перейдите на лицензионный|License|license|upgrade|Upgrade|тарифный план" "$file" 2>/dev/null; then
echo " Удаление лицензии из: $file"
# Удаляем строки про лицензию
docker exec "${CONTAINER_NAME}" sed -i '/лицензионный тарифный план/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Перейдите на лицензионный/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/расширенные возможности/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/настраиваемую тематику/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/фирменный стиль/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/специальную поддержку/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/License/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Лицензия/d' "$file" 2>/dev/null || true
fi
fi
done
echo "5. Удаление всего блока 'Помощь' (Help section)..."
docker exec "${CONTAINER_NAME}" find /app/web -type f \( -name "*.svelte" -o -name "*.html" -o -name "*.js" -o -name "*.ts" \) \
! -path "*/node_modules/*" ! -path "*/.next/*" \
2>/dev/null | while read file; do
if docker exec "${CONTAINER_NAME}" file "$file" 2>/dev/null | grep -q "text\|JSON\|ASCII"; then
if docker exec "${CONTAINER_NAME}" grep -qE "Помощь|Узнайте, как использовать|обратитесь за поддержкой|Документация" "$file" 2>/dev/null; then
echo " Удаление блока помощи из: $file"
# Удаляем строки из блока помощи
docker exec "${CONTAINER_NAME}" sed -i '/Помощь/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/Узнайте, как использовать/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/обратитесь за поддержкой/d' "$file" 2>/dev/null || true
docker exec "${CONTAINER_NAME}" sed -i '/к сообществу/d' "$file" 2>/dev/null || true
fi
fi
done
echo ""
echo "6. Перезапуск контейнера..."
docker restart "${CONTAINER_NAME}" >/dev/null 2>&1 || {
echo "Предупреждение: Перезапустите вручную: docker restart ${CONTAINER_NAME}"
}
echo ""
echo "=== Удаление завершено! ==="
echo ""
echo "Проверьте:"
echo " 1. Откройте https://odo.iieasy.ru"
echo " 2. В футере не должно быть ссылок на Discord, Twitter/X, GitHub"
echo " 3. Не должно быть строки про лицензию"
echo ""
echo "ВАЖНО: Очистите кеш браузера (Ctrl+Shift+Delete)"

68
scripts/test_direct_vision.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/bin/bash
# Прямой тест vision через Ollama API (минуя Open WebUI)
set -e
CONTAINER_OLLAMA="ollama"
MODEL="gemma3n:e4b-it-fp16"
IMAGE_FILE="/home/its/iiEasyWeb/test_images/test_image.jpg"
echo "=== Прямой тест Vision через Ollama API ==="
echo ""
# Проверка файла изображения
if [ ! -f "$IMAGE_FILE" ]; then
echo "✗ Файл изображения не найден: $IMAGE_FILE"
echo "Скачайте изображение сначала"
exit 1
fi
echo "1. Кодирование изображения в base64..."
IMAGE_B64=$(base64 -w 0 "$IMAGE_FILE" 2>/dev/null || base64 "$IMAGE_FILE" | tr -d '\n')
echo " ✓ Изображение закодировано (${#IMAGE_B64} символов)"
echo ""
echo "2. Отправка запроса к Ollama API..."
echo " Модель: $MODEL"
echo " Промпт: Опиши это изображение на русском языке. Что ты видишь?"
echo ""
# Определяем команду docker
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
# Отправляем запрос
RESPONSE=$($DOCKER_CMD exec $CONTAINER_OLLAMA curl -s --max-time 120 -X POST http://localhost:11434/api/generate \
-H 'Content-Type: application/json' \
-d "{
\"model\": \"$MODEL\",
\"prompt\": \"Опиши это изображение на русском языке. Что ты видишь на картинке?\",
\"images\": [\"$IMAGE_B64\"],
\"stream\": false
}" 2>&1)
echo ""
if echo "$RESPONSE" | grep -q '"response"'; then
echo "✓ Успешно! Ответ модели:"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data.get('response', ''))" 2>/dev/null || \
echo "$RESPONSE" | grep -o '"response":"[^"]*"' | sed 's/"response":"\(.*\)"/\1/' | sed 's/\\n/\n/g' | sed 's/\\"/"/g'
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "=== ✓ Vision работает напрямую через Ollama API! ==="
echo ""
echo "Если это работает, значит проблема в Open WebUI, а не в Ollama."
echo "Возможные причины:"
echo " 1. Open WebUI v0.8.3 не поддерживает vision для gemma3n"
echo " 2. Модель не помечена как vision-модель в настройках"
echo " 3. Нужно обновить Open WebUI до более новой версии"
elif echo "$RESPONSE" | grep -q "error\|Error"; then
echo "✗ Ошибка:"
echo "$RESPONSE" | grep -i error || echo "$RESPONSE"
else
echo "⚠ Неожиданный ответ:"
echo "$RESPONSE" | head -20
fi

142
scripts/test_vision.sh Executable file
View File

@@ -0,0 +1,142 @@
#!/bin/bash
# Скрипт для тестирования vision capabilities модели gemma3n:e4b-it-fp16
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
TEST_DIR="$PROJECT_DIR/test_images"
IMAGE_URL="https://yandex-images.clstorage.net/PU5vN2154/532297ZKm/lCuSfyMn0DdbJqcFVeFiB9Ti31Te2dZ1EepiRw3Cs0Qw8cQ1ND5OQRKC1yH4LnhdRtloQ4aXHng5ZSLNmXHy_8k293YSMsBWKnOvYAXBbhPcl6pYmqi-ZGWDazZo2pYkJNHpkJHrg5yiO0bEOIeEICe5cFqrojYgyNQ6mHj4e5IUb_Lri3uxo9fmXv0dMf7f1NvH9J5YVsyhRvvmtD9eTc1QfVxV42d8OotKrLTDfHx7jfDqjpIqHAyt9ngIIHsSjLtOJ7_jTYdHLn4hJWlCj_jj69gGlApIBYaTfoxPrtHFDGlYUd-PjHI3hijAm6hIb-lUFlpOehQAJTbwEGwjcqjjVns323WrR2q6CalVyg9kZ8s0jkBm8OVGr26UH86NHaD1rKnPH6zinwJIKBv8VEdF_FrGLt6QFOVqFOQY776w47YDNy8Biwfefg0lxVaL2E9L5NbAztwh8vuCcMNSEfG8aYQFBxe0Eu9CMPhz1Axz1dgqmkpSYCAR8nSA_GMSKKPa9-tzIUc7ooKthV1ykwSjrzhORKq0eRrvBlTbajF5yAUoVX-7XM7HouyU51xMaxFMBl7atixQFW4o1BznMoi_chuL8_mTO_IKce21CosEQ6Owkkhi9EGSz5pIE56NjURBxKn7pwTKt6K4FB_YYHexZG4qlsIg8GVaiJyIB0p0bx5PF4_FIy-SItWZId5f8M9_RIqg2hRVCqP2hDvSfWGAYUjJd6c8lr9mgGj7kPQbVQBCUgIm1NB9lsxQrIO-wO92fytbOQsjjiqBqa0CK9Qjy6wi6CoIfX5vZjw_pj1BKGm0UVOXuArPFngIN2AUgz3w4mZSTvz8IQYo_IhPVlQ7PiOjhyWD6wZSVZ3NDrvsC-8w4lxmzE32T1qMuy5JOTRxaNHHH0QCp4IkgMv8LH8JeJaOUj4sVOGCBBgQi5KMX74TQzOBW9cGTu35UZr3qAfj5O6kMogxjqNanMOs"
IMAGE_FILE="$TEST_DIR/test_image.jpg"
MODEL="gemma3n:e4b-it-fp16"
echo "=== Тестирование Vision Capabilities модели $MODEL ==="
echo ""
# Определяем команду docker (с sudo или без)
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
# Проверка контейнера Ollama
echo "1. Проверка контейнера Ollama..."
if ! $DOCKER_CMD ps --format '{{.Names}}' 2>/dev/null | grep -q "^ollama$"; then
echo " ✗ Ошибка: Контейнер ollama не запущен"
echo " Запустите: docker compose up -d ollama"
exit 1
fi
echo " ✓ Контейнер ollama запущен"
# Проверка модели
echo ""
echo "2. Проверка загруженных моделей..."
MODELS=$($DOCKER_CMD exec ollama ollama list 2>/dev/null)
if echo "$MODELS" | grep -q "$MODEL"; then
echo " ✓ Модель $MODEL найдена"
echo "$MODELS" | grep "$MODEL"
else
echo " ✗ Модель $MODEL не найдена"
echo " Загрузите модель: docker exec ollama ollama pull $MODEL"
exit 1
fi
# Создаем директорию для тестовых изображений
mkdir -p "$TEST_DIR"
cd "$TEST_DIR"
# Скачиваем изображение
echo ""
echo "3. Подготовка тестового изображения..."
if [ ! -f "$IMAGE_FILE" ]; then
echo " Скачиваю изображение..."
curl -L -o "$IMAGE_FILE" "$IMAGE_URL" || {
echo " ✗ Ошибка: не удалось скачать изображение"
exit 1
}
echo " ✓ Изображение скачано: $IMAGE_FILE"
else
echo " ✓ Изображение уже существует: $IMAGE_FILE"
fi
# Проверяем размер файла
if [ -f "$IMAGE_FILE" ]; then
FILE_SIZE=$(stat -c%s "$IMAGE_FILE" 2>/dev/null || stat -f%z "$IMAGE_FILE" 2>/dev/null)
echo " Размер файла: $(numfmt --to=iec-i --suffix=B $FILE_SIZE 2>/dev/null || echo "${FILE_SIZE} bytes")"
# Проверяем тип файла
FILE_TYPE=$(file "$IMAGE_FILE" 2>/dev/null | cut -d: -f2)
echo " Тип файла: $FILE_TYPE"
fi
# Кодируем изображение в base64
echo ""
echo "4. Кодирование изображения в base64..."
IMAGE_B64=$(base64 -w 0 "$IMAGE_FILE" 2>/dev/null || base64 "$IMAGE_FILE" | tr -d '\n')
B64_LENGTH=${#IMAGE_B64}
echo " ✓ Изображение закодировано (длина: $B64_LENGTH символов)"
# Отправляем запрос к Ollama API
echo ""
echo "5. Отправка запроса к Ollama API..."
echo " Модель: $MODEL"
echo " Промпт: Опиши это изображение на русском языке. Что ты видишь на картинке?"
echo ""
# Отправляем запрос через Docker exec к Ollama API
# Используем временный файл для передачи большого base64
echo " Отправка запроса (это может занять некоторое время)..."
TEMP_FILE=$(mktemp)
cat > "$TEMP_FILE" <<EOF
{
"model": "$MODEL",
"prompt": "Опиши это изображение на русском языке. Что ты видишь на картинке?",
"images": ["$IMAGE_B64"],
"stream": false
}
EOF
# Копируем файл в контейнер и отправляем запрос
$DOCKER_CMD cp "$TEMP_FILE" ollama:/tmp/request.json >/dev/null 2>&1
RESPONSE=$($DOCKER_CMD exec ollama sh -c "curl -s --max-time 120 -X POST http://localhost:11434/api/generate \
-H 'Content-Type: application/json' \
-d @/tmp/request.json" 2>&1)
# Удаляем временный файл
rm -f "$TEMP_FILE"
# Проверяем ответ
if echo "$RESPONSE" | grep -q '"response"'; then
echo " ✓ Успешно! Ответ модели:"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Извлекаем ответ более надежным способом
echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data.get('response', ''))" 2>/dev/null || \
echo "$RESPONSE" | grep -o '"response":"[^"]*"' | sed 's/"response":"\(.*\)"/\1/' | sed 's/\\n/\n/g' | sed 's/\\"/"/g' | head -20
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "=== ✓ Тест завершен успешно! Vision работает! ==="
elif echo "$RESPONSE" | grep -q "error\|Error\|ERROR"; then
echo " ✗ Ошибка при запросе к API:"
echo "$RESPONSE" | grep -i error || echo "$RESPONSE"
echo ""
echo "Проверьте:"
echo " 1. Логи Ollama: $DOCKER_CMD logs ollama --tail 30"
echo " 2. Поддерживает ли модель vision: $DOCKER_CMD exec ollama ollama show $MODEL"
else
echo " ⚠ Неожиданный ответ от API:"
echo "$RESPONSE"
echo ""
echo "Попробуйте проверить через веб-интерфейс Open WebUI"
fi
echo ""
echo "6. Инструкции для тестирования через веб-интерфейс:"
echo ""
echo " Шаг 1: Откройте Open WebUI: https://odo.iieasy.ru"
echo " Шаг 2: Выберите модель: $MODEL"
echo " Шаг 3: Найдите кнопку загрузки изображения в поле ввода (📎 или 📷)"
echo " Шаг 4: Загрузите изображение: $IMAGE_FILE"
echo " Шаг 5: Задайте вопрос: \"Опиши это изображение на русском языке. Что ты видишь?\""
echo ""
echo "Файл изображения: $IMAGE_FILE"

50
scripts/update.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
# Скрипт для обновления Open WebUI до последней версии
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
CONTAINER_NAME="open-webui"
echo "=== Обновление Open WebUI ==="
echo ""
cd "$PROJECT_DIR"
# Проверка текущей версии в docker-compose.yml
CURRENT_VERSION=$(grep "image: ghcr.io/open-webui/open-webui:" docker-compose.yml | sed 's/.*:\(.*\)/\1/')
echo "Текущая версия в docker-compose.yml: $CURRENT_VERSION"
echo ""
echo "1. Получение новых образов..."
sudo docker compose pull
echo ""
echo "2. Остановка контейнеров..."
sudo docker compose stop
echo ""
echo "3. Пересоздание контейнеров с новыми образами..."
sudo docker compose up -d
echo ""
echo "4. Ожидание запуска контейнеров (30 секунд)..."
sleep 30
echo ""
echo "5. Применение ребрендинга..."
if [ -f "$SCRIPT_DIR/rebrand.sh" ]; then
"$SCRIPT_DIR/rebrand.sh"
else
echo "⚠ Скрипт rebrand.sh не найден, пропускаем ребрендинг"
fi
echo ""
echo "=== Обновление завершено! ==="
echo ""
echo "Проверьте статус:"
echo " sudo docker compose ps"
echo ""
echo "Проверьте логи:"
echo " sudo docker compose logs open-webui --tail 50"