From 9aa5aefdad1873cd6fdcbd31ae7af816908d5ca0 Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Tue, 28 Oct 2025 18:57:28 +0600 Subject: [PATCH 1/6] docs synced --- CHANGELOG.txt | 30 ++++++++++++++++++++++++++++++ docs/README.md | 13 +++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f997f37..4a1dd39 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,36 @@ CHANGELOG ========= +Версия 2.0.6 (2025-10-28) +========================= + +## ✨ НОВОЕ И ИЗМЕНЕНО + +- 🌐 Поддержка BasePath для всех веб‑роутов и шаблонов + - Новый параметр: `LCG_BASE_URL` (пример: `/lcg`) — префикс для всех страниц и API + - Обновлены редиректы и middleware с учетом BasePath +- 🧭 Кастомная страница 404 (красная тема), показывается для любого неизвестного пути под BasePath +- 📱 Улучшена мобильная верстка результатов — стиль карточек как в истории +- 🗂️ Человекочитаемые заголовки результатов: преобразование имени файла в «заголовок — дата время» +- 🗑️ Иконки удаления: единый бледно‑красный крест ✖ в результатах и истории + +## 🐛 ИСПРАВЛЕНИЯ + +- 🛡️ Исправлен просмотр/удаление файла при включенном BasePath (правильный разбор URL) +- 🧰 На старте сервера гарантируется создание `ResultFolder` и пустого `ResultHistory` (без 500) +- 🚧 Главная страница обрабатывается только по точному пути BasePath, а не по произвольным под‑путям + +## ⚙️ КОНФИГУРАЦИЯ + +- 🔍 Debug режим теперь включается и флагом `--debug`, и переменной `LCG_DEBUG=1|true` +- 🍪 Уточнена работа с `CookiePath`/`BasePath` в middleware + +## 📚 ДОКУМЕНТАЦИЯ + +- Обновлены `README.md`, `USAGE_GUIDE.md`, `API_GUIDE.md`, `REVERSE_PROXY_GUIDE.md` — добавлены примеры с BasePath и примечания к 404 + +--- + Версия 2.0.1 (2025-10-22) ========================= diff --git a/docs/README.md b/docs/README.md index 29a51a0..05eec33 100644 --- a/docs/README.md +++ b/docs/README.md @@ -133,10 +133,15 @@ The `serve` command provides both a web interface and REST API: **Web Interface:** -- Browse results at `http://localhost:8080/` -- Execute requests at `http://localhost:8080/run` -- Manage prompts at `http://localhost:8080/prompts` -- View history at `http://localhost:8080/history` +- Browse results at `http://localhost:8080/` (or `http://localhost:8080/` if `LCG_BASE_URL` set) +- Execute requests at `.../run` +- Manage prompts at `.../prompts` +- View history at `.../history` + +Notes: +- Base path: set `LCG_BASE_URL` (e.g. `/lcg`) to prefix all routes and API. +- Custom 404: unknown paths under base path render a modern 404 page. +- Debug: enable via flag `--debug` or env `LCG_DEBUG=1|true`. **REST API:** From 1e2ce929b2efd98f9ffbe5cb78eecab0aed6839e Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Tue, 28 Oct 2025 19:07:50 +0600 Subject: [PATCH 2/6] release to github 2.0.14 --- deploy/.goreleaser.yaml | 2 + deploy/release-goreleaser.sh | 126 +++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 deploy/release-goreleaser.sh diff --git a/deploy/.goreleaser.yaml b/deploy/.goreleaser.yaml index 3fce9f5..d0f5909 100644 --- a/deploy/.goreleaser.yaml +++ b/deploy/.goreleaser.yaml @@ -9,6 +9,8 @@ builds: goarch: - amd64 - arm64 + - windows + - darwin env: - CGO_ENABLED=0 ldflags: diff --git a/deploy/release-goreleaser.sh b/deploy/release-goreleaser.sh new file mode 100644 index 0000000..0aa084a --- /dev/null +++ b/deploy/release-goreleaser.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env bash +set -euo pipefail + +# release-goreleaser.sh +# Копирует deploy/.goreleaser.yaml в корень, запускает релиз и удаляет файл. +# +# Использование: +# deploy/release-goreleaser.sh # обычный релиз на GitHub (нужен GITHUB_TOKEN) +# deploy/release-goreleaser.sh --snapshot # локальный снепшот без публикации + +ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +SRC_CFG="$ROOT_DIR/deploy/.goreleaser.yaml" +DST_CFG="$ROOT_DIR/.goreleaser.yaml" + +log() { echo -e "\033[36m[release]\033[0m $*"; } +err() { echo -e "\033[31m[error]\033[0m $*" >&2; } + +if ! command -v goreleaser >/dev/null 2>&1; then + err "goreleaser не найден. Установите: https://goreleaser.com/install/" + exit 1 +fi + +if [[ ! -f "$SRC_CFG" ]]; then + err "Не найден файл конфигурации: $SRC_CFG" + exit 1 +fi + +MODE="release" +if [[ "${1:-}" == "--snapshot" ]]; then + MODE="snapshot" + shift || true +fi + +if [[ -f "$DST_CFG" ]]; then + err "В корне уже существует .goreleaser.yaml. Удалите/переименуйте перед запуском." + exit 1 +fi + +cleanup() { + if [[ -f "$DST_CFG" ]]; then + rm -f "$DST_CFG" || true + log "Удалил временный $DST_CFG" + fi +} +trap cleanup EXIT + +log "Копирую конфиг: $SRC_CFG -> $DST_CFG" +cp "$SRC_CFG" "$DST_CFG" + +pushd "$ROOT_DIR" >/dev/null + +## Версию берём из deploy/VERSION.txt или VERSION.txt в корне +VERSION_FILE="$ROOT_DIR/deploy/VERSION.txt" +[[ -f "$VERSION_FILE" ]] || VERSION_FILE="$ROOT_DIR/VERSION.txt" +if [[ -f "$VERSION_FILE" ]]; then + VERSION_RAW="$(head -n1 "$VERSION_FILE" | tr -d ' \t\r\n')" + if [[ -n "$VERSION_RAW" ]]; then + TAG="$VERSION_RAW" + [[ "$TAG" == v* ]] || TAG="v$TAG" + export GORELEASER_CURRENT_TAG="$TAG" + log "Версия релиза: $TAG (из $(realpath --relative-to="$ROOT_DIR" "$VERSION_FILE" 2>/dev/null || echo "$VERSION_FILE"))" + fi +fi + +create_and_push_tag() { + local tag="$1" + if git rev-parse "$tag" >/dev/null 2>&1; then + log "Git tag уже существует: $tag" + else + log "Создаю git tag: $tag" + git tag -a "$tag" -m "Release $tag" + if [[ "${NO_GIT_PUSH:-false}" != "true" ]]; then + log "Пушу тег $tag на origin" + git push origin "$tag" + else + log "Пропущен пуш тега (NO_GIT_PUSH=true)" + fi + fi +} + +fetch_token_from_k8s() { + export KUBECONFIG=/home/su/.kube/config_hlab + local ns="${K8S_NAMESPACE:-flux-system}" + local name="${K8S_SECRET_NAME:-git-secrets}" + # Предпочитаем jq (как в примере), при отсутствии используем jsonpath + base64 -d + if command -v jq >/dev/null 2>&1; then + kubectl get secret "$name" -n "$ns" -o json \ + | jq -r '.data.password | @base64d' + else + kubectl get secret "$name" -n "$ns" -o jsonpath='{.data.password}' \ + | base64 -d 2>/dev/null || true + fi +} + +if [[ "$MODE" == "snapshot" ]]; then + log "Запуск goreleaser (snapshot, без публикации)" + goreleaser release --snapshot --clean --config "$DST_CFG" +else + # Если версия определена и тега нет — создадим (goreleaser ориентируется на теги) + if [[ -n "${GORELEASER_CURRENT_TAG:-}" ]]; then + create_and_push_tag "$GORELEASER_CURRENT_TAG" + fi + if [[ -z "${GITHUB_TOKEN:-}" ]]; then + log "GITHUB_TOKEN не задан — пробую получить из k8s секрета (${K8S_NAMESPACE:-flux-system}/${K8S_SECRET_NAME:-git-secrets}, ключ: password)" + if ! command -v kubectl >/dev/null 2>&1; then + err "kubectl не найден, а GITHUB_TOKEN не задан. Установите kubectl или экспортируйте GITHUB_TOKEN." + exit 1 + fi + TOKEN_FROM_K8S="$(fetch_token_from_k8s || true)" + if [[ -n "$TOKEN_FROM_K8S" && "$TOKEN_FROM_K8S" != "null" ]]; then + export GITHUB_TOKEN="$TOKEN_FROM_K8S" + log "GITHUB_TOKEN получен из секрета Kubernetes." + else + err "Не удалось получить GITHUB_TOKEN из секрета Kubernetes. Экспортируйте GITHUB_TOKEN и повторите." + exit 1 + fi + fi + log "Запуск goreleaser (публикация на GitHub)" + goreleaser release --clean --config "$DST_CFG" +fi + +popd >/dev/null + +log "Готово." + + From 4779c4bca489497b0af3c9048b5ea81657c40040 Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Tue, 28 Oct 2025 19:09:57 +0600 Subject: [PATCH 3/6] chore: temp goreleaser config [skip ci] --- .goreleaser.yaml | 32 ++++++++++++++++++++++++ deploy/.goreleaser.yaml | 9 ++++--- deploy/release-goreleaser.sh | 48 ++++++++++++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 .goreleaser.yaml diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..1a11f75 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,32 @@ +# Goreleaser configuration version 2 +version: 2 + +builds: + - id: lcg + binary: "lcg_{{ .Version }}" + goos: + - linux + - windows + - darwin + goarch: + - amd64 + - arm64 + env: + - CGO_ENABLED=0 + ldflags: + - -s -w + - -X main.version={{.Version}} + - -X main.commit={{.Commit}} + - -X main.date={{.Date}} + main: . + dir: . + +archives: + - id: lcg + ids: + - lcg + formats: + - binary + name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" + files: + - "lcg_{{ .Version }}" diff --git a/deploy/.goreleaser.yaml b/deploy/.goreleaser.yaml index d0f5909..1a11f75 100644 --- a/deploy/.goreleaser.yaml +++ b/deploy/.goreleaser.yaml @@ -6,11 +6,11 @@ builds: binary: "lcg_{{ .Version }}" goos: - linux + - windows + - darwin goarch: - amd64 - arm64 - - windows - - darwin env: - CGO_ENABLED=0 ldflags: @@ -23,9 +23,10 @@ builds: archives: - id: lcg - builds: + ids: - lcg - format: binary + formats: + - binary name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" files: - "lcg_{{ .Version }}" diff --git a/deploy/release-goreleaser.sh b/deploy/release-goreleaser.sh index 0aa084a..55c6066 100644 --- a/deploy/release-goreleaser.sh +++ b/deploy/release-goreleaser.sh @@ -49,6 +49,12 @@ cp "$SRC_CFG" "$DST_CFG" pushd "$ROOT_DIR" >/dev/null +EXTRA_FLAGS=() +PREV_HEAD="$(git rev-parse HEAD 2>/dev/null || echo "")" + +git add . +git commit --amend --no-edit || true + ## Версию берём из deploy/VERSION.txt или VERSION.txt в корне VERSION_FILE="$ROOT_DIR/deploy/VERSION.txt" [[ -f "$VERSION_FILE" ]] || VERSION_FILE="$ROOT_DIR/VERSION.txt" @@ -78,6 +84,25 @@ create_and_push_tag() { fi } +move_tag_to_head() { + local tag="$1" + if [[ -z "$tag" ]]; then + return 0 + fi + if git rev-parse "$tag" >/dev/null 2>&1; then + log "Переношу тег $tag на текущий коммит (HEAD)" + git tag -f "$tag" HEAD + if [[ "${NO_GIT_PUSH:-false}" != "true" ]]; then + log "Форс‑пуш тега $tag на origin" + git push -f origin "$tag" + else + log "Пропущен пуш тега (NO_GIT_PUSH=true)" + fi + else + log "Тега $tag нет — пропускаю перенос" + fi +} + fetch_token_from_k8s() { export KUBECONFIG=/home/su/.kube/config_hlab local ns="${K8S_NAMESPACE:-flux-system}" @@ -94,11 +119,21 @@ fetch_token_from_k8s() { if [[ "$MODE" == "snapshot" ]]; then log "Запуск goreleaser (snapshot, без публикации)" - goreleaser release --snapshot --clean --config "$DST_CFG" + goreleaser release --snapshot --clean --config "$DST_CFG" "${EXTRA_FLAGS[@]}" else # Если версия определена и тега нет — создадим (goreleaser ориентируется на теги) if [[ -n "${GORELEASER_CURRENT_TAG:-}" ]]; then create_and_push_tag "$GORELEASER_CURRENT_TAG" + # Перемещаем тег на текущий HEAD (если существовал ранее, закрепим на последнем коммите) + move_tag_to_head "$GORELEASER_CURRENT_TAG" + else + # Если версия не задана, попробуем взять последний существующий тег и перенести его на HEAD + LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || true)" + if [[ -n "$LAST_TAG" ]]; then + move_tag_to_head "$LAST_TAG" + export GORELEASER_CURRENT_TAG="$LAST_TAG" + log "Использую последний тег: $LAST_TAG" + fi fi if [[ -z "${GITHUB_TOKEN:-}" ]]; then log "GITHUB_TOKEN не задан — пробую получить из k8s секрета (${K8S_NAMESPACE:-flux-system}/${K8S_SECRET_NAME:-git-secrets}, ключ: password)" @@ -116,11 +151,20 @@ else fi fi log "Запуск goreleaser (публикация на GitHub)" - goreleaser release --clean --config "$DST_CFG" + goreleaser release --clean --config "$DST_CFG" "${EXTRA_FLAGS[@]}" fi popd >/dev/null +# Откатываем временный коммит, если он был +if [[ "${TEMP_COMMIT_DONE:-false}" == "true" && -n "$PREV_HEAD" ]]; then + if git reset --soft "$PREV_HEAD" >/dev/null 2>&1; then + log "Откатил временный коммит" + else + log "Не удалось откатить временный коммит — проверьте историю вручную" + fi +fi + log "Готово." From eb9a7dcf321754962147f59b2854f7d0cd28af0a Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Sat, 8 Nov 2025 15:59:45 +0600 Subject: [PATCH 4/6] v2.0.15 --- .goreleaser.yaml | 32 -- Dockerfiles/OllamaServer/.dockerignore | 52 +++ Dockerfiles/OllamaServer/.gitignore | 15 + Dockerfiles/OllamaServer/Dockerfile | 78 ++++ Dockerfiles/OllamaServer/Makefile | 107 ++++++ Dockerfiles/OllamaServer/QUICKSTART.md | 172 +++++++++ Dockerfiles/OllamaServer/README.md | 397 ++++++++++++++++++++ Dockerfiles/OllamaServer/STRUCTURE.md | 111 ++++++ Dockerfiles/OllamaServer/docker-compose.yml | 54 +++ Dockerfiles/OllamaServer/entrypoint.sh | 171 +++++++++ Dockerfiles/OllamaServer/podman-compose.yml | 54 +++ VERSION.txt | 2 +- deploy/VERSION.txt | 2 +- docs/CONFIG_COMMAND.md | 16 +- docs/README.md | 13 +- docs/USAGE_GUIDE.md | 4 +- docs/VALIDATION_CONFIG.md | 72 ++-- main.go | 60 ++- serve/serve.go | 10 +- serve/templates/not_found.go | 16 +- 20 files changed, 1339 insertions(+), 99 deletions(-) delete mode 100644 .goreleaser.yaml create mode 100644 Dockerfiles/OllamaServer/.dockerignore create mode 100644 Dockerfiles/OllamaServer/.gitignore create mode 100644 Dockerfiles/OllamaServer/Dockerfile create mode 100644 Dockerfiles/OllamaServer/Makefile create mode 100644 Dockerfiles/OllamaServer/QUICKSTART.md create mode 100644 Dockerfiles/OllamaServer/README.md create mode 100644 Dockerfiles/OllamaServer/STRUCTURE.md create mode 100644 Dockerfiles/OllamaServer/docker-compose.yml create mode 100755 Dockerfiles/OllamaServer/entrypoint.sh create mode 100644 Dockerfiles/OllamaServer/podman-compose.yml diff --git a/.goreleaser.yaml b/.goreleaser.yaml deleted file mode 100644 index 1a11f75..0000000 --- a/.goreleaser.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Goreleaser configuration version 2 -version: 2 - -builds: - - id: lcg - binary: "lcg_{{ .Version }}" - goos: - - linux - - windows - - darwin - goarch: - - amd64 - - arm64 - env: - - CGO_ENABLED=0 - ldflags: - - -s -w - - -X main.version={{.Version}} - - -X main.commit={{.Commit}} - - -X main.date={{.Date}} - main: . - dir: . - -archives: - - id: lcg - ids: - - lcg - formats: - - binary - name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" - files: - - "lcg_{{ .Version }}" diff --git a/Dockerfiles/OllamaServer/.dockerignore b/Dockerfiles/OllamaServer/.dockerignore new file mode 100644 index 0000000..c4e1bb4 --- /dev/null +++ b/Dockerfiles/OllamaServer/.dockerignore @@ -0,0 +1,52 @@ +# Git +.git +.gitignore +.gitattributes + +# Build artifacts +dist/ +*.exe +*.dll +*.so +*.dylib +lcg +go-lcg + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Documentation +docs/ +*.md +!README.md + +# Tests +*_test.go +test_*.sh + +# Deployment scripts +deploy/ +shell-code/ +kustomize/ + +# Temporary files +*.log +*.tmp +*.temp + +# OS files +.DS_Store +Thumbs.db + +# Go +vendor/ + +# Docker +Dockerfile* +docker-compose*.yml +.dockerignore + diff --git a/Dockerfiles/OllamaServer/.gitignore b/Dockerfiles/OllamaServer/.gitignore new file mode 100644 index 0000000..77d13f0 --- /dev/null +++ b/Dockerfiles/OllamaServer/.gitignore @@ -0,0 +1,15 @@ +# Временные файлы +*.log +*.tmp +*.temp + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + diff --git a/Dockerfiles/OllamaServer/Dockerfile b/Dockerfiles/OllamaServer/Dockerfile new file mode 100644 index 0000000..6a73f6f --- /dev/null +++ b/Dockerfiles/OllamaServer/Dockerfile @@ -0,0 +1,78 @@ +# Multi-stage build для LCG с Ollama +FROM golang:1.24.6-alpine3.22 AS builder + +WORKDIR /build + +# Копируем файлы зависимостей +COPY go.mod go.sum ./ +RUN go mod download + +# Копируем исходный код +COPY . . + +# Собираем бинарник +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s -buildid=" -trimpath -o /build/lcg . + +# Финальный образ с Ollama +FROM alpine:3.22 + +# Устанавливаем необходимые пакеты +RUN apk add --no-cache \ + curl \ + ca-certificates \ + bash \ + && rm -rf /var/cache/apk/* + +# Устанавливаем Ollama 0.9.5 (поддержка разных архитектур) +ARG TARGETARCH +RUN case ${TARGETARCH} in \ + amd64) OLLAMA_ARCH=amd64 ;; \ + arm64) OLLAMA_ARCH=arm64 ;; \ + arm) OLLAMA_ARCH=arm64 ;; \ + *) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \ + esac && \ + curl -L https://github.com/ollama/ollama/releases/download/v0.9.5/ollama-linux-${OLLAMA_ARCH} -o /usr/local/bin/ollama \ + && chmod +x /usr/local/bin/ollama + +# Создаем пользователя для запуска сервисов +RUN addgroup -g 1000 ollama && \ + adduser -D -u 1000 -G ollama ollama && \ + mkdir -p /home/ollama/.ollama && \ + chown -R ollama:ollama /home/ollama + +# Копируем бинарник lcg +COPY --from=builder /build/lcg /usr/local/bin/lcg +RUN chmod +x /usr/local/bin/lcg + +# Копируем entrypoint скрипт +COPY --chmod=755 Dockerfiles/OllamaServer/entrypoint.sh /entrypoint.sh + +# Создаем директории для данных +RUN mkdir -p /app/data/results /app/data/prompts /app/data/config \ + && chown -R ollama:ollama /app/data + +# Настройки по умолчанию +ENV LCG_PROVIDER=ollama +ENV LCG_HOST=http://127.0.0.1:11434/ +ENV LCG_MODEL=codegeex4 +ENV LCG_RESULT_FOLDER=/app/data/results +ENV LCG_PROMPT_FOLDER=/app/data/prompts +ENV LCG_CONFIG_FOLDER=/app/data/config +ENV LCG_SERVER_HOST=0.0.0.0 +ENV LCG_SERVER_PORT=8080 +ENV LCG_SERVER_ALLOW_HTTP=true +ENV OLLAMA_HOST=0.0.0.0 +ENV OLLAMA_PORT=11434 + +# Expose порты +EXPOSE 8080 11434 + +# Переключаемся на пользователя ollama +USER ollama + +WORKDIR /home/ollama + +# Запускаем entrypoint +ENTRYPOINT ["/entrypoint.sh"] +CMD [] + diff --git a/Dockerfiles/OllamaServer/Makefile b/Dockerfiles/OllamaServer/Makefile new file mode 100644 index 0000000..8e2b43c --- /dev/null +++ b/Dockerfiles/OllamaServer/Makefile @@ -0,0 +1,107 @@ +.PHONY: build build-podman run run-podman stop stop-podman logs logs-podman clean help + +# Переменные +IMAGE_NAME = lcg-ollama +IMAGE_TAG = latest +CONTAINER_NAME = lcg-ollama +DOCKERFILE = Dockerfile +CONTEXT = ../.. + +help: ## Показать справку + @echo "Доступные команды:" + @echo " make build - Собрать Docker образ" + @echo " make build-podman - Собрать Podman образ" + @echo " make run - Запустить контейнер (Docker)" + @echo " make run-podman - Запустить контейнер (Podman)" + @echo " make stop - Остановить контейнер (Docker)" + @echo " make stop-podman - Остановить контейнер (Podman)" + @echo " make logs - Показать логи (Docker)" + @echo " make logs-podman - Показать логи (Podman)" + @echo " make clean - Удалить контейнер и образ" + @echo " make compose-up - Запустить через docker-compose" + @echo " make compose-down - Остановить docker-compose" + @echo " make podman-compose-up - Запустить через podman-compose" + @echo " make podman-compose-down - Остановить podman-compose" + +build: ## Собрать Docker образ + docker build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) + @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" + +build-podman: ## Собрать Podman образ + podman build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) + @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" + +run: ## Запустить контейнер (Docker) + docker run -d \ + --name $(CONTAINER_NAME) \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + $(IMAGE_NAME):$(IMAGE_TAG) + @echo "Контейнер $(CONTAINER_NAME) запущен" + +run-podman: ## Запустить контейнер (Podman) + podman run -d \ + --name $(CONTAINER_NAME) \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + $(IMAGE_NAME):$(IMAGE_TAG) + @echo "Контейнер $(CONTAINER_NAME) запущен" + +stop: ## Остановить контейнер (Docker) + docker stop $(CONTAINER_NAME) || true + docker rm $(CONTAINER_NAME) || true + @echo "Контейнер $(CONTAINER_NAME) остановлен и удален" + +stop-podman: ## Остановить контейнер (Podman) + podman stop $(CONTAINER_NAME) || true + podman rm $(CONTAINER_NAME) || true + @echo "Контейнер $(CONTAINER_NAME) остановлен и удален" + +logs: ## Показать логи (Docker) + docker logs -f $(CONTAINER_NAME) + +logs-podman: ## Показать логи (Podman) + podman logs -f $(CONTAINER_NAME) + +clean: ## Удалить контейнер и образ + docker stop $(CONTAINER_NAME) || true + docker rm $(CONTAINER_NAME) || true + docker rmi $(IMAGE_NAME):$(IMAGE_TAG) || true + @echo "Контейнер и образ удалены" + +compose-up: ## Запустить через docker-compose + docker-compose up -d + @echo "Сервисы запущены через docker-compose" + +compose-down: ## Остановить docker-compose + docker-compose down + @echo "Сервисы остановлены" + +podman-compose-up: ## Запустить через podman-compose + podman-compose -f podman-compose.yml up -d + @echo "Сервисы запущены через podman-compose" + +podman-compose-down: ## Остановить podman-compose + podman-compose -f podman-compose.yml down + @echo "Сервисы остановлены" + +shell: ## Подключиться к контейнеру (Docker) + docker exec -it $(CONTAINER_NAME) sh + +shell-podman: ## Подключиться к контейнеру (Podman) + podman exec -it $(CONTAINER_NAME) sh + +pull-model: ## Загрузить модель codegeex4 (Docker) + docker exec $(CONTAINER_NAME) ollama pull codegeex4 + +pull-model-podman: ## Загрузить модель codegeex4 (Podman) + podman exec $(CONTAINER_NAME) ollama pull codegeex4 + diff --git a/Dockerfiles/OllamaServer/QUICKSTART.md b/Dockerfiles/OllamaServer/QUICKSTART.md new file mode 100644 index 0000000..bb8faa8 --- /dev/null +++ b/Dockerfiles/OllamaServer/QUICKSTART.md @@ -0,0 +1,172 @@ +# 🚀 Быстрый старт - LCG с Ollama + +## Подготовка + +1. Убедитесь, что у вас установлен Docker или Podman +2. Клонируйте репозиторий (если еще не сделали) +3. Перейдите в папку с Dockerfile + +```bash +cd Dockerfiles/OllamaServer +``` + +## Запуск с Docker + +### Вариант 1: Docker Compose (рекомендуется) + +```bash +docker-compose up -d +``` + +### Вариант 2: Ручная сборка и запуск + +```bash +# Сборка образа +docker build -f Dockerfile -t lcg-ollama:latest ../.. + +# Запуск контейнера +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + lcg-ollama:latest +``` + +## Запуск с Podman + +### Вариант 1: Podman Compose + +```bash +podman-compose -f podman-compose.yml up -d +``` + +### Вариант 2: Ручная сборка и запуск + +```bash +# Сборка образа +podman build -f Dockerfile -t lcg-ollama:latest ../.. + +# Запуск контейнера +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + lcg-ollama:latest +``` + +## Проверка запуска + +### Проверка логов + +```bash +# Docker +docker logs -f lcg-ollama + +# Podman +podman logs -f lcg-ollama +``` + +Дождитесь сообщений: +- `Ollama сервер готов!` +- `LCG сервер запущен на http://0.0.0.0:8080` + +### Проверка доступности + +```bash +# Проверка Ollama +curl http://localhost:11434/api/tags + +# Проверка LCG +curl http://localhost:8080/ +``` + +## Загрузка модели + +После запуска контейнера загрузите модель: + +```bash +# Docker +docker exec lcg-ollama ollama pull codegeex4 + +# Podman +podman exec lcg-ollama ollama pull codegeex4 +``` + +Или используйте модель по умолчанию, указанную в переменных окружения. + +## Доступ к веб-интерфейсу + +Откройте в браузере: http://localhost:8080 + +## Остановка + +```bash +# Docker +docker-compose down + +# Podman +podman-compose -f podman-compose.yml down +``` + +Или для ручного запуска: + +```bash +# Docker +docker stop lcg-ollama +docker rm lcg-ollama + +# Podman +podman stop lcg-ollama +podman rm lcg-ollama +``` + +## Решение проблем + +### Порт занят + +Измените порты в docker-compose.yml или команде run: + +```bash +-p 9000:8080 # LCG на порту 9000 +-p 11435:11434 # Ollama на порту 11435 +``` + +### Контейнер не запускается + +Проверьте логи: + +```bash +docker logs lcg-ollama +# или +podman logs lcg-ollama +``` + +### Модель не загружена + +Убедитесь, что модель существует: + +```bash +docker exec lcg-ollama ollama list +# или +podman exec lcg-ollama ollama list +``` + +Если модели нет, загрузите её: + +```bash +docker exec lcg-ollama ollama pull codegeex4 +# или +podman exec lcg-ollama ollama pull codegeex4 +``` + +## Следующие шаги + +- Прочитайте полную документацию в [README.md](README.md) +- Настройте аутентификацию для продакшена +- Настройте reverse proxy для HTTPS +- Загрузите нужные модели Ollama + diff --git a/Dockerfiles/OllamaServer/README.md b/Dockerfiles/OllamaServer/README.md new file mode 100644 index 0000000..1652453 --- /dev/null +++ b/Dockerfiles/OllamaServer/README.md @@ -0,0 +1,397 @@ +# 🐳 LCG с Ollama Server - Docker/Podman контейнер + +Этот образ содержит Linux Command GPT (LCG) и Ollama сервер, работающие вместе в одном контейнере. + +Поддерживается запуск через Docker и Podman. + +## 📋 Описание + +Контейнер автоматически запускает: +1. **Ollama сервер** (v0.9.5) на порту 11434 +2. **LCG веб-сервер** на порту 8080 + +Ollama используется как провайдер LLM для генерации Linux команд. + +## 🚀 Быстрый старт + +### Сборка образа + +#### Docker +```bash +# Из корня проекта +docker build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . +``` + +#### Podman +```bash +# Из корня проекта +podman build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . +``` + +### Запуск контейнера + +#### Docker +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Podman +```bash +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +### Использование docker-compose / podman-compose + +#### Docker Compose +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +#### Podman Compose +```bash +cd Dockerfiles/OllamaServer +podman-compose -f podman-compose.yml up -d +``` + +Или используйте встроенную поддержку Podman: +```bash +cd Dockerfiles/OllamaServer +podman play kube podman-compose.yml +``` + +## 🌐 Доступ к сервисам + +После запуска контейнера доступны: + +- **LCG веб-интерфейс**: http://localhost:8080 +- **Ollama API**: http://localhost:11434 + +## ⚙️ Переменные окружения + +### Настройки LCG + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `LCG_PROVIDER` | `ollama` | Тип провайдера | +| `LCG_HOST` | `http://127.0.0.1:11434/` | URL Ollama API | +| `LCG_MODEL` | `codegeex4` | Модель для использования | +| `LCG_SERVER_HOST` | `0.0.0.0` | Хост LCG сервера | +| `LCG_SERVER_PORT` | `8080` | Порт LCG сервера | +| `LCG_SERVER_ALLOW_HTTP` | `true` | Разрешить HTTP | +| `LCG_RESULT_FOLDER` | `/app/data/results` | Папка для результатов | +| `LCG_PROMPT_FOLDER` | `/app/data/prompts` | Папка для промптов | +| `LCG_CONFIG_FOLDER` | `/app/data/config` | Папка для конфигурации | + +### Настройки Ollama + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `OLLAMA_HOST` | `127.0.0.1` | Хост Ollama сервера | +| `OLLAMA_PORT` | `11434` | Порт Ollama сервера | + +### Безопасность + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `LCG_SERVER_REQUIRE_AUTH` | `false` | Требовать аутентификацию | +| `LCG_SERVER_PASSWORD` | `admin#123456` | Пароль для аутентификации | + +## 📦 Volumes + +Рекомендуется монтировать volumes для персистентного хранения данных: + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + lcg-ollama:latest +``` + +### Volumes описание + +- `ollama-data`: Модели и данные Ollama +- `lcg-results`: Результаты генерации команд +- `lcg-prompts`: Системные промпты +- `lcg-config`: Конфигурация LCG + +## 🔧 Примеры использования + +### Запуск с кастомной моделью + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -e LCG_MODEL=llama3:8b \ + lcg-ollama:latest +``` + +### Запуск с аутентификацией + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -e LCG_SERVER_REQUIRE_AUTH=true \ + -e LCG_SERVER_PASSWORD=my_secure_password \ + lcg-ollama:latest +``` + +### Запуск с кастомным портом + +```bash +docker run -d \ + --name lcg-ollama \ + -p 9000:9000 \ + -p 11434:11434 \ + -e LCG_SERVER_PORT=9000 \ + lcg-ollama:latest +``` + +## 📥 Загрузка моделей Ollama + +После запуска контейнера можно загрузить модели: + +```bash +# Подключиться к контейнеру +docker exec -it lcg-ollama sh + +# Загрузить модель +ollama pull codegeex4 +ollama pull llama3:8b +ollama pull qwen2.5:7b +``` + +Или извне контейнера: + +```bash +# Убедитесь, что Ollama доступен извне (OLLAMA_HOST=0.0.0.0) +docker exec lcg-ollama ollama pull codegeex4 +``` + +## 🔍 Проверка работоспособности + +### Проверка Ollama + +```bash +# Проверка health +curl http://localhost:11434/api/tags + +# Список моделей +curl http://localhost:11434/api/tags | jq '.models' +``` + +### Проверка LCG + +```bash +# Проверка веб-интерфейса +curl http://localhost:8080/ + +# Проверка через API +curl -X POST http://localhost:8080/api/execute \ + -H "Content-Type: application/json" \ + -d '{"prompt": "создать директорию test"}' +``` + +## 🐧 Podman специфичные инструкции + +### Запуск с Podman + +Podman работает аналогично Docker, но есть несколько отличий: + +#### Создание сетей (если нужно) + +```bash +podman network create lcg-network +``` + +#### Запуск с сетью + +```bash +podman run -d \ + --name lcg-ollama \ + --network lcg-network \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Запуск в rootless режиме + +Podman по умолчанию работает в rootless режиме, что повышает безопасность: + +```bash +# Не требует sudo +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Использование systemd для автозапуска + +Создайте systemd unit файл: + +```bash +# Генерируем unit файл +podman generate systemd --name lcg-ollama --files + +# Копируем в systemd +sudo cp container-lcg-ollama.service /etc/systemd/system/ + +# Включаем автозапуск +sudo systemctl enable container-lcg-ollama.service +sudo systemctl start container-lcg-ollama.service +``` + +#### Проверка статуса + +```bash +# Статус контейнера +podman ps + +# Логи +podman logs lcg-ollama + +# Логи в реальном времени +podman logs -f lcg-ollama +``` + +## 🐛 Отладка + +### Просмотр логов + +#### Docker +```bash +# Логи контейнера +docker logs lcg-ollama + +# Логи в реальном времени +docker logs -f lcg-ollama +``` + +#### Podman +```bash +# Логи контейнера +podman logs lcg-ollama + +# Логи в реальном времени +podman logs -f lcg-ollama +``` + +### Подключение к контейнеру + +#### Docker +```bash +docker exec -it lcg-ollama sh +``` + +#### Podman +```bash +podman exec -it lcg-ollama sh +``` + +### Проверка процессов + +#### Docker +```bash +docker exec lcg-ollama ps aux +``` + +#### Podman +```bash +podman exec lcg-ollama ps aux +``` + +## 🔒 Безопасность + +### Рекомендации для продакшена + +1. **Используйте аутентификацию**: + ```bash + -e LCG_SERVER_REQUIRE_AUTH=true + -e LCG_SERVER_PASSWORD=strong_password + ``` + +2. **Ограничьте доступ к портам**: + - Используйте firewall правила + - Не экспортируйте порты на публичный интерфейс + +3. **Используйте HTTPS**: + - Настройте reverse proxy (nginx, traefik) + - Используйте SSL сертификаты + +4. **Ограничьте ресурсы**: + ```bash + docker run -d \ + --name lcg-ollama \ + --memory="4g" \ + --cpus="2" \ + lcg-ollama:latest + ``` + +## 📊 Мониторинг + +### Healthcheck + +Контейнер включает healthcheck, который проверяет доступность LCG сервера: + +```bash +docker inspect lcg-ollama | jq '.[0].State.Health' +``` + +### Метрики + +LCG предоставляет Prometheus метрики на `/metrics` endpoint (если включено). + +## 🚀 Production Deployment + +### С docker-compose + +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +### С Kubernetes + +Используйте манифесты из папки `deploy/` или `kustomize/`. + +## 📝 Примечания + +- Ollama версия: 0.9.5 +- LCG версия: см. VERSION.txt +- Минимальные требования: 2GB RAM, 2 CPU cores +- Рекомендуется: 4GB+ RAM для больших моделей + +## 🔗 Полезные ссылки + +- [Ollama документация](https://github.com/ollama/ollama) +- [LCG документация](../../docs/README.md) +- [LCG API Guide](../../docs/API_GUIDE.md) + +## ❓ Поддержка + +При возникновении проблем: +1. Проверьте логи: `docker logs lcg-ollama` +2. Проверьте переменные окружения +3. Убедитесь, что порты не заняты +4. Проверьте, что модели загружены в Ollama + diff --git a/Dockerfiles/OllamaServer/STRUCTURE.md b/Dockerfiles/OllamaServer/STRUCTURE.md new file mode 100644 index 0000000..4efc13e --- /dev/null +++ b/Dockerfiles/OllamaServer/STRUCTURE.md @@ -0,0 +1,111 @@ +# 📁 Структура проекта OllamaServer + +## Файлы + +``` +Dockerfiles/OllamaServer/ +├── Dockerfile # Multi-stage Dockerfile для сборки образа +├── entrypoint.sh # Скрипт запуска LCG и Ollama серверов +├── docker-compose.yml # Docker Compose конфигурация +├── podman-compose.yml # Podman Compose конфигурация +├── Makefile # Команды для сборки и запуска +├── README.md # Полная документация +├── QUICKSTART.md # Быстрый старт +├── STRUCTURE.md # Этот файл +├── .dockerignore # Исключения для Docker build +└── .gitignore # Исключения для Git +``` + +## Описание файлов + +### Dockerfile +Multi-stage Dockerfile, который: +1. Собирает бинарник LCG из исходного кода +2. Устанавливает Ollama 0.9.5 +3. Создает пользователя ollama +4. Настраивает рабочее окружение + +### entrypoint.sh +Скрипт запуска, который: +1. Запускает Ollama сервер в фоне +2. Ожидает готовности Ollama API +3. Запускает LCG сервер в фоне +4. Мониторит состояние процессов +5. Корректно обрабатывает сигналы завершения + +### docker-compose.yml / podman-compose.yml +Конфигурация для запуска через compose: +- Настройки портов +- Переменные окружения +- Volumes для персистентного хранения +- Healthcheck + +### Makefile +Удобные команды для: +- Сборки образа +- Запуска/остановки контейнера +- Просмотра логов +- Работы с compose + +### README.md +Полная документация с: +- Описанием функциональности +- Инструкциями по установке +- Настройками переменных окружения +- Примерами использования +- Решением проблем + +### QUICKSTART.md +Краткое руководство для быстрого старта. + +## Порты + +- **8080**: LCG веб-сервер +- **11434**: Ollama API + +## Volumes + +- `ollama-data`: Данные Ollama (модели) +- `lcg-results`: Результаты генерации команд +- `lcg-prompts`: Системные промпты +- `lcg-config`: Конфигурация LCG + +## Переменные окружения + +Основные переменные (см. README.md для полного списка): +- `LCG_PROVIDER=ollama` +- `LCG_HOST=http://127.0.0.1:11434/` +- `LCG_MODEL=codegeex4` +- `OLLAMA_HOST=0.0.0.0` +- `OLLAMA_PORT=11434` + +## Запуск + +### Docker +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +### Podman +```bash +cd Dockerfiles/OllamaServer +podman-compose -f podman-compose.yml up -d +``` + +### Make +```bash +cd Dockerfiles/OllamaServer +make compose-up +# или +make podman-compose-up +``` + +## Архитектура + +Контейнер запускает два сервиса: +1. **Ollama** (порт 11434) - LLM сервер +2. **LCG** (порт 8080) - Веб-интерфейс и API + +Оба сервиса работают в одном контейнере и общаются через localhost. + diff --git a/Dockerfiles/OllamaServer/docker-compose.yml b/Dockerfiles/OllamaServer/docker-compose.yml new file mode 100644 index 0000000..ca76825 --- /dev/null +++ b/Dockerfiles/OllamaServer/docker-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + lcg-ollama: + build: + context: ../.. + dockerfile: Dockerfiles/OllamaServer/Dockerfile + container_name: lcg-ollama + ports: + - "8080:8080" # LCG веб-сервер + - "11434:11434" # Ollama API + environment: + # Настройки LCG + - LCG_PROVIDER=ollama + - LCG_HOST=http://127.0.0.1:11434/ + - LCG_MODEL=codegeex4 + - LCG_RESULT_FOLDER=/app/data/results + - LCG_PROMPT_FOLDER=/app/data/prompts + - LCG_CONFIG_FOLDER=/app/data/config + - LCG_SERVER_HOST=0.0.0.0 + - LCG_SERVER_PORT=8080 + - LCG_SERVER_ALLOW_HTTP=true + # Настройки Ollama + - OLLAMA_HOST=0.0.0.0 + - OLLAMA_PORT=11434 + - OLLAMA_ORIGINS=* + # Опционально: настройки безопасности + - LCG_SERVER_REQUIRE_AUTH=false + - LCG_SERVER_PASSWORD=admin#123456 + volumes: + # Персистентное хранилище для данных Ollama + - ollama-data:/home/ollama/.ollama + # Персистентное хранилище для результатов LCG + - lcg-results:/app/data/results + - lcg-prompts:/app/data/prompts + - lcg-config:/app/data/config + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +volumes: + ollama-data: + driver: local + lcg-results: + driver: local + lcg-prompts: + driver: local + lcg-config: + driver: local + diff --git a/Dockerfiles/OllamaServer/entrypoint.sh b/Dockerfiles/OllamaServer/entrypoint.sh new file mode 100755 index 0000000..f7b6f97 --- /dev/null +++ b/Dockerfiles/OllamaServer/entrypoint.sh @@ -0,0 +1,171 @@ +#!/bin/bash +set -e + +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Функция для логирования +log() { + echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" >&2 +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Обработка сигналов для корректного завершения +cleanup() { + log "Получен сигнал завершения, останавливаем сервисы..." + if [ ! -z "$LCG_PID" ]; then + kill $LCG_PID 2>/dev/null || true + wait $LCG_PID 2>/dev/null || true + fi + if [ ! -z "$OLLAMA_PID" ]; then + kill $OLLAMA_PID 2>/dev/null || true + wait $OLLAMA_PID 2>/dev/null || true + fi + log "Сервисы остановлены" + exit 0 +} + +trap cleanup SIGTERM SIGINT + +# Проверка наличия бинарника lcg +if [ ! -f /usr/local/bin/lcg ]; then + error "Бинарник lcg не найден в /usr/local/bin/lcg" + exit 1 +fi + +# Проверка наличия Ollama +if [ ! -f /usr/local/bin/ollama ]; then + error "Ollama не найден в /usr/local/bin/ollama" + exit 1 +fi + +# Создаем необходимые директории +mkdir -p "${LCG_RESULT_FOLDER:-/app/data/results}" +mkdir -p "${LCG_PROMPT_FOLDER:-/app/data/prompts}" +mkdir -p "${LCG_CONFIG_FOLDER:-/app/data/config}" + +# Настройка переменных окружения для Ollama +export OLLAMA_HOST="${OLLAMA_HOST:-0.0.0.0}" +export OLLAMA_PORT="${OLLAMA_PORT:-11434}" +export OLLAMA_ORIGINS="*" + +# Настройка переменных окружения для LCG +export LCG_PROVIDER="${LCG_PROVIDER:-ollama}" +export LCG_HOST="${LCG_HOST:-http://127.0.0.1:11434/}" +export LCG_MODEL="${LCG_MODEL:-codegeex4}" +export LCG_RESULT_FOLDER="${LCG_RESULT_FOLDER:-/app/data/results}" +export LCG_PROMPT_FOLDER="${LCG_PROMPT_FOLDER:-/app/data/prompts}" +export LCG_CONFIG_FOLDER="${LCG_CONFIG_FOLDER:-/app/data/config}" +export LCG_SERVER_HOST="${LCG_SERVER_HOST:-0.0.0.0}" +export LCG_SERVER_PORT="${LCG_SERVER_PORT:-8080}" +export LCG_SERVER_ALLOW_HTTP="${LCG_SERVER_ALLOW_HTTP:-true}" + +log "==========================================" +log "Запуск LCG с Ollama сервером" +log "==========================================" +info "LCG Provider: $LCG_PROVIDER" +info "LCG Host: $LCG_HOST" +info "LCG Model: $LCG_MODEL" +info "LCG Server: http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" +info "Ollama Host: $OLLAMA_HOST:$OLLAMA_PORT" +log "==========================================" + +# Запускаем Ollama сервер в фоне +log "Запуск Ollama сервера..." +/usr/local/bin/ollama serve & +OLLAMA_PID=$! + +# Ждем, пока Ollama запустится +log "Ожидание запуска Ollama сервера..." +sleep 5 + +# Проверяем, что Ollama запущен +if ! kill -0 $OLLAMA_PID 2>/dev/null; then + error "Ollama сервер не запустился" + exit 1 +fi + +# Проверяем доступность Ollama API +max_attempts=30 +attempt=0 +while [ $attempt -lt $max_attempts ]; do + # Проверяем через localhost, так как OLLAMA_HOST может быть 0.0.0.0 + if curl -s -f "http://127.0.0.1:${OLLAMA_PORT}/api/tags" > /dev/null 2>&1; then + log "Ollama сервер готов!" + break + fi + attempt=$((attempt + 1)) + if [ $attempt -eq $max_attempts ]; then + error "Ollama сервер не отвечает после $max_attempts попыток" + exit 1 + fi + sleep 1 +done + +# Запускаем LCG сервер в фоне +log "Запуск LCG сервера..." +/usr/local/bin/lcg serve \ + --host "${LCG_SERVER_HOST}" \ + --port "${LCG_SERVER_PORT}" & +LCG_PID=$! + +# Ждем, пока LCG запустится +sleep 3 + +# Проверяем, что LCG запущен +if ! kill -0 $LCG_PID 2>/dev/null; then + error "LCG сервер не запустился" + kill $OLLAMA_PID 2>/dev/null || true + exit 1 +fi + +log "LCG сервер запущен на http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" +log "Ollama сервер доступен на http://${OLLAMA_HOST}:${OLLAMA_PORT}" +log "==========================================" +log "Сервисы запущены и готовы к работе!" +log "==========================================" + +# Функция для проверки здоровья процессов +health_check() { + while true; do + # Проверяем Ollama + if ! kill -0 $OLLAMA_PID 2>/dev/null; then + error "Ollama процесс завершился неожиданно" + kill $LCG_PID 2>/dev/null || true + exit 1 + fi + + # Проверяем LCG + if ! kill -0 $LCG_PID 2>/dev/null; then + error "LCG процесс завершился неожиданно" + kill $OLLAMA_PID 2>/dev/null || true + exit 1 + fi + + sleep 10 + done +} + +# Запускаем проверку здоровья в фоне +health_check & +HEALTH_CHECK_PID=$! + +# Ждем завершения процессов +wait $LCG_PID $OLLAMA_PID +kill $HEALTH_CHECK_PID 2>/dev/null || true + diff --git a/Dockerfiles/OllamaServer/podman-compose.yml b/Dockerfiles/OllamaServer/podman-compose.yml new file mode 100644 index 0000000..ca76825 --- /dev/null +++ b/Dockerfiles/OllamaServer/podman-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + lcg-ollama: + build: + context: ../.. + dockerfile: Dockerfiles/OllamaServer/Dockerfile + container_name: lcg-ollama + ports: + - "8080:8080" # LCG веб-сервер + - "11434:11434" # Ollama API + environment: + # Настройки LCG + - LCG_PROVIDER=ollama + - LCG_HOST=http://127.0.0.1:11434/ + - LCG_MODEL=codegeex4 + - LCG_RESULT_FOLDER=/app/data/results + - LCG_PROMPT_FOLDER=/app/data/prompts + - LCG_CONFIG_FOLDER=/app/data/config + - LCG_SERVER_HOST=0.0.0.0 + - LCG_SERVER_PORT=8080 + - LCG_SERVER_ALLOW_HTTP=true + # Настройки Ollama + - OLLAMA_HOST=0.0.0.0 + - OLLAMA_PORT=11434 + - OLLAMA_ORIGINS=* + # Опционально: настройки безопасности + - LCG_SERVER_REQUIRE_AUTH=false + - LCG_SERVER_PASSWORD=admin#123456 + volumes: + # Персистентное хранилище для данных Ollama + - ollama-data:/home/ollama/.ollama + # Персистентное хранилище для результатов LCG + - lcg-results:/app/data/results + - lcg-prompts:/app/data/prompts + - lcg-config:/app/data/config + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +volumes: + ollama-data: + driver: local + lcg-results: + driver: local + lcg-prompts: + driver: local + lcg-config: + driver: local + diff --git a/VERSION.txt b/VERSION.txt index 68496c0..0e18aae 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -v2.0.14 +v2.0.15 diff --git a/deploy/VERSION.txt b/deploy/VERSION.txt index 68496c0..0e18aae 100644 --- a/deploy/VERSION.txt +++ b/deploy/VERSION.txt @@ -1 +1 @@ -v2.0.14 +v2.0.15 diff --git a/docs/CONFIG_COMMAND.md b/docs/CONFIG_COMMAND.md index 1b35f76..70ef9af 100644 --- a/docs/CONFIG_COMMAND.md +++ b/docs/CONFIG_COMMAND.md @@ -69,8 +69,8 @@ lcg co -f "host": "localhost" }, "validation": { - "max_system_prompt_length": 1000, - "max_user_message_length": 2000, + "max_system_prompt_length": 2000, + "max_user_message_length": 4000, "max_prompt_name_length": 2000, "max_prompt_desc_length": 5000, "max_command_length": 8000, @@ -116,12 +116,12 @@ lcg co -f ### Настройки валидации (validation) -- **max_system_prompt_length** - максимальная длина системного промпта -- **max_user_message_length** - максимальная длина пользовательского сообщения -- **max_prompt_name_length** - максимальная длина названия промпта -- **max_prompt_desc_length** - максимальная длина описания промпта -- **max_command_length** - максимальная длина команды/ответа -- **max_explanation_length** - максимальная длина объяснения +- **max_system_prompt_length** - максимальная длина системного промпта (по умолчанию: 2000) +- **max_user_message_length** - максимальная длина пользовательского сообщения (по умолчанию: 4000) +- **max_prompt_name_length** - максимальная длина названия промпта (по умолчанию: 2000) +- **max_prompt_desc_length** - максимальная длина описания промпта (по умолчанию: 5000) +- **max_command_length** - максимальная длина команды/ответа (по умолчанию: 8000) +- **max_explanation_length** - максимальная длина объяснения (по умолчанию: 20000) ## 🔒 Безопасность diff --git a/docs/README.md b/docs/README.md index 05eec33..d5bcf78 100644 --- a/docs/README.md +++ b/docs/README.md @@ -35,10 +35,17 @@ Explanations: Clipboard support requires `xclip` or `xsel`. -## What's new in 2.0.1 +## What's new in 2.0.14 -- Mobile UI improvements: better responsiveness (buttons, fonts, spacing) and reduced motion support -- Public REST endpoint: `POST /execute` (curl-only) for programmatic access — see `API_GUIDE.md` +- Authentication: JWT-based authentication with HTTP-only cookies +- CSRF protection: Full CSRF protection with tokens and middleware +- Security: Enhanced security with token validation and sessions +- Kubernetes deployment: Full set of manifests for Kubernetes deployment with Traefik +- Reverse Proxy: Support for working behind reverse proxy with cookie configuration +- Web interface: Improved web interface with modern design +- Monitoring: Prometheus metrics and ServiceMonitor +- Scaling: HPA for automatic scaling +- Testing: CSRF protection testing tools ## Environment diff --git a/docs/USAGE_GUIDE.md b/docs/USAGE_GUIDE.md index 4c74dc8..c408c51 100644 --- a/docs/USAGE_GUIDE.md +++ b/docs/USAGE_GUIDE.md @@ -22,7 +22,7 @@ sudo apt-get install xsel ```bash -git clone --depth 1 https://github.com/Direct-Dev-Ru/go-lcg.git ~/.linux-command-gpt +git clone --depth 1 https://github.com/Direct-Dev-Ru/linux-command-gpt.git ~/.linux-command-gpt cd ~/.linux-command-gpt go build -o lcg @@ -60,7 +60,7 @@ lcg --file /path/to/context.txt "хочу вывести список дирек Действия: (c)копировать, (s)сохранить, (r)перегенерировать, (e)выполнить, (v|vv|vvv)подробно, (n)ничего: ``` -### Что нового в 3.0.0 +### Что нового в 2.0.14 - **Аутентификация**: Добавлена система аутентификации с JWT токенами и HTTP-only cookies - **CSRF защита**: Полная защита от CSRF атак с токенами и middleware diff --git a/docs/VALIDATION_CONFIG.md b/docs/VALIDATION_CONFIG.md index e1f2d9d..de88b96 100644 --- a/docs/VALIDATION_CONFIG.md +++ b/docs/VALIDATION_CONFIG.md @@ -8,26 +8,26 @@ | Переменная | Описание | По умолчанию | |------------|----------|--------------| -| `LCG_MAX_SYSTEM_PROMPT_LENGTH` | Максимальная длина системного промпта | 1000 | -| `LCG_MAX_USER_MESSAGE_LENGTH` | Максимальная длина пользовательского сообщения | 2000 | -| `LCG_MAX_PROMPT_NAME_LENGTH` | Максимальная длина названия промпта | 200 | -| `LCG_MAX_PROMPT_DESC_LENGTH` | Максимальная длина описания промпта | 500 | -| `LCG_MAX_COMMAND_LENGTH` | Максимальная длина команды/ответа | 2000 | -| `LCG_MAX_EXPLANATION_LENGTH` | Максимальная длина объяснения | 2000 | +| `LCG_MAX_SYSTEM_PROMPT_LENGTH` | Максимальная длина системного промпта | 2000 | +| `LCG_MAX_USER_MESSAGE_LENGTH` | Максимальная длина пользовательского сообщения | 4000 | +| `LCG_MAX_PROMPT_NAME_LENGTH` | Максимальная длина названия промпта | 2000 | +| `LCG_MAX_PROMPT_DESC_LENGTH` | Максимальная длина описания промпта | 5000 | +| `LCG_MAX_COMMAND_LENGTH` | Максимальная длина команды/ответа | 8000 | +| `LCG_MAX_EXPLANATION_LENGTH` | Максимальная длина объяснения | 20000 | ## 🚀 Примеры использования ### Установка через переменные окружения ```bash -# Увеличить лимит системного промпта до 2к символов -export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 +# Увеличить лимит системного промпта до 3к символов +export LCG_MAX_SYSTEM_PROMPT_LENGTH=3000 -# Уменьшить лимит пользовательского сообщения до 1к символов -export LCG_MAX_USER_MESSAGE_LENGTH=1000 +# Уменьшить лимит пользовательского сообщения до 2к символов +export LCG_MAX_USER_MESSAGE_LENGTH=2000 -# Увеличить лимит названия промпта до 500 символов -export LCG_MAX_PROMPT_NAME_LENGTH=500 +# Увеличить лимит названия промпта до 3000 символов +export LCG_MAX_PROMPT_NAME_LENGTH=3000 ``` ### Установка в .env файле @@ -35,11 +35,11 @@ export LCG_MAX_PROMPT_NAME_LENGTH=500 ```bash # .env файл LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -LCG_MAX_USER_MESSAGE_LENGTH=1500 -LCG_MAX_PROMPT_NAME_LENGTH=300 -LCG_MAX_PROMPT_DESC_LENGTH=1000 -LCG_MAX_COMMAND_LENGTH=3000 -LCG_MAX_EXPLANATION_LENGTH=5000 +LCG_MAX_USER_MESSAGE_LENGTH=4000 +LCG_MAX_PROMPT_NAME_LENGTH=2000 +LCG_MAX_PROMPT_DESC_LENGTH=5000 +LCG_MAX_COMMAND_LENGTH=8000 +LCG_MAX_EXPLANATION_LENGTH=20000 ``` ### Установка в systemd сервисе @@ -55,8 +55,8 @@ User=lcg WorkingDirectory=/opt/lcg ExecStart=/opt/lcg/lcg serve Environment=LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -Environment=LCG_MAX_USER_MESSAGE_LENGTH=1500 -Environment=LCG_MAX_PROMPT_NAME_LENGTH=300 +Environment=LCG_MAX_USER_MESSAGE_LENGTH=4000 +Environment=LCG_MAX_PROMPT_NAME_LENGTH=2000 Restart=always [Install] @@ -72,7 +72,7 @@ FROM golang:1.21-alpine AS builder FROM alpine:latest COPY --from=builder /app/lcg /usr/local/bin/ ENV LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -ENV LCG_MAX_USER_MESSAGE_LENGTH=1500 +ENV LCG_MAX_USER_MESSAGE_LENGTH=4000 CMD ["lcg", "serve"] ``` @@ -84,8 +84,8 @@ services: image: lcg:latest environment: - LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 - - LCG_MAX_USER_MESSAGE_LENGTH=1500 - - LCG_MAX_PROMPT_NAME_LENGTH=300 + - LCG_MAX_USER_MESSAGE_LENGTH=4000 + - LCG_MAX_PROMPT_NAME_LENGTH=2000 ports: - "8080:8080" ``` @@ -153,9 +153,9 @@ validation.FormatLengthInfo(systemPrompt, userMessage) ## 📝 Примеры сообщений об ошибках ``` -❌ Ошибка: system_prompt: системный промпт слишком длинный: 1500 символов (максимум 1000) -❌ Ошибка: user_message: пользовательское сообщение слишком длинное: 2500 символов (максимум 2000) -❌ Ошибка: prompt_name: название промпта слишком длинное: 300 символов (максимум 200) +❌ Ошибка: system_prompt: системный промпт слишком длинный: 2500 символов (максимум 2000) +❌ Ошибка: user_message: пользовательское сообщение слишком длинное: 4500 символов (максимум 4000) +❌ Ошибка: prompt_name: название промпта слишком длинное: 2500 символов (максимум 2000) ``` ## 🔄 Миграция с жестко заданных значений @@ -179,25 +179,25 @@ if err := validation.ValidateSystemPrompt(prompt); err != nil { ### Для разработки ```bash export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -export LCG_MAX_USER_MESSAGE_LENGTH=2000 -export LCG_MAX_PROMPT_NAME_LENGTH=200 -export LCG_MAX_PROMPT_DESC_LENGTH=500 +export LCG_MAX_USER_MESSAGE_LENGTH=4000 +export LCG_MAX_PROMPT_NAME_LENGTH=2000 +export LCG_MAX_PROMPT_DESC_LENGTH=5000 ``` ### Для продакшена ```bash -export LCG_MAX_SYSTEM_PROMPT_LENGTH=1000 -export LCG_MAX_USER_MESSAGE_LENGTH=1500 -export LCG_MAX_PROMPT_NAME_LENGTH=100 -export LCG_MAX_PROMPT_DESC_LENGTH=300 +export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 +export LCG_MAX_USER_MESSAGE_LENGTH=4000 +export LCG_MAX_PROMPT_NAME_LENGTH=2000 +export LCG_MAX_PROMPT_DESC_LENGTH=5000 ``` ### Для высоконагруженных систем ```bash -export LCG_MAX_SYSTEM_PROMPT_LENGTH=500 -export LCG_MAX_USER_MESSAGE_LENGTH=1000 -export LCG_MAX_PROMPT_NAME_LENGTH=50 -export LCG_MAX_PROMPT_DESC_LENGTH=200 +export LCG_MAX_SYSTEM_PROMPT_LENGTH=1000 +export LCG_MAX_USER_MESSAGE_LENGTH=2000 +export LCG_MAX_PROMPT_NAME_LENGTH=1000 +export LCG_MAX_PROMPT_DESC_LENGTH=2500 ``` --- diff --git a/main.go b/main.go index 114314f..eb86f93 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func main() { CompileConditions.NoServe = false } - fmt.Println("Build conditions:", CompileConditions) + // fmt.Println("Build conditions:", CompileConditions) _ = colorBlue @@ -87,12 +87,56 @@ lcg [опции] <описание команды> {{.AppName}} - инструмент для генерации Linux команд из описаний на естественном языке. Поддерживает чтение частей промпта из файлов и позволяет сохранять, копировать или перегенерировать результаты. может задавать системный промпт или выбирать из предустановленных промптов. + Переменные окружения: - LCG_HOST Endpoint для LLM API (по умолчанию: http://192.168.87.108:11434/) - LCG_MODEL Название модели (по умолчанию: codegeex4) - LCG_PROMPT Текст промпта по умолчанию - LCG_PROVIDER Тип провайдера: "ollama" или "proxy" (по умолчанию: ollama) - LCG_JWT_TOKEN JWT токен для proxy провайдера + +Основные настройки: + LCG_HOST Endpoint для LLM API (по умолчанию: http://192.168.87.108:11434/) + LCG_MODEL Название модели (по умолчанию: hf.co/yandex/YandexGPT-5-Lite-8B-instruct-GGUF:Q4_K_M) + LCG_PROMPT Текст промпта по умолчанию + LCG_PROVIDER Тип провайдера: "ollama" или "proxy" (по умолчанию: ollama) + LCG_JWT_TOKEN JWT токен для proxy провайдера + LCG_PROMPT_ID ID промпта по умолчанию (по умолчанию: 1) + LCG_TIMEOUT Таймаут запроса в секундах (по умолчанию: 300) + LCG_COMPLETIONS_PATH Путь к API для завершений (по умолчанию: api/chat) + LCG_PROXY_URL URL прокси для proxy провайдера (по умолчанию: /api/v1/protected/sberchat/chat) + LCG_API_KEY_FILE Файл с API ключом (по умолчанию: .openai_api_key) + LCG_APP_NAME Название приложения (по умолчанию: Linux Command GPT) + +Настройки истории и выполнения: + LCG_NO_HISTORY Отключить запись истории ("1" или "true" = отключено, пусто = включено) + LCG_ALLOW_EXECUTION Разрешить выполнение команд ("1" или "true" = разрешено, пусто = запрещено) + LCG_RESULT_FOLDER Папка для сохранения результатов (по умолчанию: ~/.config/lcg/gpt_results) + LCG_RESULT_HISTORY Файл истории результатов (по умолчанию: /lcg_history.json) + LCG_PROMPT_FOLDER Папка для системных промптов (по умолчанию: ~/.config/lcg/gpt_sys_prompts) + LCG_CONFIG_FOLDER Папка для конфигурации (по умолчанию: ~/.config/lcg/config) + +Настройки сервера (команда serve): + LCG_SERVER_PORT Порт сервера (по умолчанию: 8080) + LCG_SERVER_HOST Хост сервера (по умолчанию: localhost) + LCG_SERVER_ALLOW_HTTP Разрешить HTTP соединения ("true" для localhost, "false" для других хостов) + LCG_SERVER_REQUIRE_AUTH Требовать аутентификацию ("1" или "true" = требуется, пусто = не требуется) + LCG_SERVER_PASSWORD Пароль администратора (по умолчанию: admin#123456) + LCG_SERVER_SSL_CERT_FILE Путь к SSL сертификату + LCG_SERVER_SSL_KEY_FILE Путь к приватному ключу SSL + LCG_DOMAIN Домен для сервера (по умолчанию: значение LCG_SERVER_HOST) + LCG_COOKIE_SECURE Безопасные cookie ("1" или "true" = включено, пусто = выключено) + LCG_COOKIE_PATH Путь для cookie (по умолчанию: /lcg) + LCG_COOKIE_TTL_HOURS Время жизни cookie в часах (по умолчанию: 168) + LCG_BASE_URL Базовый URL приложения (по умолчанию: /lcg) + LCG_HEALTH_URL URL для проверки здоровья API (по умолчанию: /api/v1/protected/sberchat/health) + +Настройки валидации: + LCG_MAX_SYSTEM_PROMPT_LENGTH Максимальная длина системного промпта (по умолчанию: 2000) + LCG_MAX_USER_MESSAGE_LENGTH Максимальная длина пользовательского сообщения (по умолчанию: 4000) + LCG_MAX_PROMPT_NAME_LENGTH Максимальная длина названия промпта (по умолчанию: 2000) + LCG_MAX_PROMPT_DESC_LENGTH Максимальная длина описания промпта (по умолчанию: 5000) + LCG_MAX_COMMAND_LENGTH Максимальная длина команды (по умолчанию: 8000) + LCG_MAX_EXPLANATION_LENGTH Максимальная длина объяснения (по умолчанию: 20000) + +Отладка и браузер: + LCG_DEBUG Включить режим отладки ("1" или "true" = включено, пусто = выключено) + LCG_BROWSER_PATH Путь к браузеру для автоматического открытия (команда serve --browser) `, Flags: []cli.Flag{ &cli.StringFlag{ @@ -159,8 +203,8 @@ lcg [опции] <описание команды> config.AppConfig.MainFlags.Debug = config.AppConfig.MainFlags.Debug || config.GetEnvBool("LCG_DEBUG", false) - fmt.Println("Debug:", config.AppConfig.MainFlags.Debug) - fmt.Println("LCG_DEBUG:", config.GetEnvBool("LCG_DEBUG", false)) + // fmt.Println("Debug:", config.AppConfig.MainFlags.Debug) + // fmt.Println("LCG_DEBUG:", config.GetEnvBool("LCG_DEBUG", false)) args := c.Args().Slice() diff --git a/serve/serve.go b/serve/serve.go index f05dd78..d0d8244 100644 --- a/serve/serve.go +++ b/serve/serve.go @@ -232,11 +232,11 @@ func registerRoutesExceptHome() { http.HandleFunc(makePath("/api/add-to-history"), AuthMiddleware(CSRFMiddleware(handleAddToHistory))) // Catch-all 404 для любых незарегистрированных путей (только когда BasePath задан) - if getBasePath() != "" { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - renderNotFound(w, "Страница не найдена", getBasePath()) - }) - } + // if getBasePath() != "" { + // http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + // renderNotFound(w, "Страница не найдена", getBasePath()) + // }) + // } } // registerRoutes регистрирует все маршруты сервера diff --git a/serve/templates/not_found.go b/serve/templates/not_found.go index 09296d0..99c90f4 100644 --- a/serve/templates/not_found.go +++ b/serve/templates/not_found.go @@ -53,6 +53,16 @@ const NotFoundTemplate = ` backdrop-filter: blur(10px); text-align: center; } + @keyframes pulse { + 0%, 100% { + transform: scale(1); + text-shadow: 0 8px 40px var(--accentGlow); + } + 50% { + transform: scale(1.15); + text-shadow: 0 12px 60px var(--accentGlow), 0 0 30px var(--accentGlow2); + } + } .code { font-size: clamp(48px, 12vw, 120px); line-height: 0.9; @@ -64,6 +74,8 @@ const NotFoundTemplate = ` color: transparent; margin: 8px 0 12px 0; text-shadow: 0 8px 40px var(--accentGlow); + animation: pulse 2.5s ease-in-out infinite; + transform-origin: center; } .title { font-size: clamp(18px, 3.2vw, 28px); @@ -133,7 +145,7 @@ const NotFoundTemplate = `
404
Страница не найдена
-

{{.Message}}

+

Такой страницы не существует. Вы можете вернуться на главную страницу или выполнить команду.

🏠 На главную 🚀 К выполнению @@ -143,5 +155,3 @@ const NotFoundTemplate = ` ` - - From 63876a393c514df49e2a63d998a42efbacbf0d9f Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Sat, 8 Nov 2025 15:59:45 +0600 Subject: [PATCH 5/6] v2.0.15 --- .goreleaser.yaml | 32 -- Dockerfiles/OllamaServer/.dockerignore | 52 +++ Dockerfiles/OllamaServer/.gitignore | 15 + Dockerfiles/OllamaServer/Dockerfile | 78 ++++ Dockerfiles/OllamaServer/Makefile | 107 ++++++ Dockerfiles/OllamaServer/QUICKSTART.md | 172 +++++++++ Dockerfiles/OllamaServer/README.md | 397 ++++++++++++++++++++ Dockerfiles/OllamaServer/STRUCTURE.md | 111 ++++++ Dockerfiles/OllamaServer/docker-compose.yml | 54 +++ Dockerfiles/OllamaServer/entrypoint.sh | 171 +++++++++ Dockerfiles/OllamaServer/podman-compose.yml | 54 +++ VERSION.txt | 2 +- deploy/VERSION.txt | 2 +- docs/CONFIG_COMMAND.md | 16 +- docs/README.md | 13 +- docs/USAGE_GUIDE.md | 4 +- docs/VALIDATION_CONFIG.md | 72 ++-- main.go | 60 ++- serve/serve.go | 10 +- serve/templates/not_found.go | 16 +- 20 files changed, 1339 insertions(+), 99 deletions(-) delete mode 100644 .goreleaser.yaml create mode 100644 Dockerfiles/OllamaServer/.dockerignore create mode 100644 Dockerfiles/OllamaServer/.gitignore create mode 100644 Dockerfiles/OllamaServer/Dockerfile create mode 100644 Dockerfiles/OllamaServer/Makefile create mode 100644 Dockerfiles/OllamaServer/QUICKSTART.md create mode 100644 Dockerfiles/OllamaServer/README.md create mode 100644 Dockerfiles/OllamaServer/STRUCTURE.md create mode 100644 Dockerfiles/OllamaServer/docker-compose.yml create mode 100755 Dockerfiles/OllamaServer/entrypoint.sh create mode 100644 Dockerfiles/OllamaServer/podman-compose.yml diff --git a/.goreleaser.yaml b/.goreleaser.yaml deleted file mode 100644 index 1a11f75..0000000 --- a/.goreleaser.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Goreleaser configuration version 2 -version: 2 - -builds: - - id: lcg - binary: "lcg_{{ .Version }}" - goos: - - linux - - windows - - darwin - goarch: - - amd64 - - arm64 - env: - - CGO_ENABLED=0 - ldflags: - - -s -w - - -X main.version={{.Version}} - - -X main.commit={{.Commit}} - - -X main.date={{.Date}} - main: . - dir: . - -archives: - - id: lcg - ids: - - lcg - formats: - - binary - name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" - files: - - "lcg_{{ .Version }}" diff --git a/Dockerfiles/OllamaServer/.dockerignore b/Dockerfiles/OllamaServer/.dockerignore new file mode 100644 index 0000000..c4e1bb4 --- /dev/null +++ b/Dockerfiles/OllamaServer/.dockerignore @@ -0,0 +1,52 @@ +# Git +.git +.gitignore +.gitattributes + +# Build artifacts +dist/ +*.exe +*.dll +*.so +*.dylib +lcg +go-lcg + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Documentation +docs/ +*.md +!README.md + +# Tests +*_test.go +test_*.sh + +# Deployment scripts +deploy/ +shell-code/ +kustomize/ + +# Temporary files +*.log +*.tmp +*.temp + +# OS files +.DS_Store +Thumbs.db + +# Go +vendor/ + +# Docker +Dockerfile* +docker-compose*.yml +.dockerignore + diff --git a/Dockerfiles/OllamaServer/.gitignore b/Dockerfiles/OllamaServer/.gitignore new file mode 100644 index 0000000..77d13f0 --- /dev/null +++ b/Dockerfiles/OllamaServer/.gitignore @@ -0,0 +1,15 @@ +# Временные файлы +*.log +*.tmp +*.temp + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + diff --git a/Dockerfiles/OllamaServer/Dockerfile b/Dockerfiles/OllamaServer/Dockerfile new file mode 100644 index 0000000..6a73f6f --- /dev/null +++ b/Dockerfiles/OllamaServer/Dockerfile @@ -0,0 +1,78 @@ +# Multi-stage build для LCG с Ollama +FROM golang:1.24.6-alpine3.22 AS builder + +WORKDIR /build + +# Копируем файлы зависимостей +COPY go.mod go.sum ./ +RUN go mod download + +# Копируем исходный код +COPY . . + +# Собираем бинарник +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s -buildid=" -trimpath -o /build/lcg . + +# Финальный образ с Ollama +FROM alpine:3.22 + +# Устанавливаем необходимые пакеты +RUN apk add --no-cache \ + curl \ + ca-certificates \ + bash \ + && rm -rf /var/cache/apk/* + +# Устанавливаем Ollama 0.9.5 (поддержка разных архитектур) +ARG TARGETARCH +RUN case ${TARGETARCH} in \ + amd64) OLLAMA_ARCH=amd64 ;; \ + arm64) OLLAMA_ARCH=arm64 ;; \ + arm) OLLAMA_ARCH=arm64 ;; \ + *) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \ + esac && \ + curl -L https://github.com/ollama/ollama/releases/download/v0.9.5/ollama-linux-${OLLAMA_ARCH} -o /usr/local/bin/ollama \ + && chmod +x /usr/local/bin/ollama + +# Создаем пользователя для запуска сервисов +RUN addgroup -g 1000 ollama && \ + adduser -D -u 1000 -G ollama ollama && \ + mkdir -p /home/ollama/.ollama && \ + chown -R ollama:ollama /home/ollama + +# Копируем бинарник lcg +COPY --from=builder /build/lcg /usr/local/bin/lcg +RUN chmod +x /usr/local/bin/lcg + +# Копируем entrypoint скрипт +COPY --chmod=755 Dockerfiles/OllamaServer/entrypoint.sh /entrypoint.sh + +# Создаем директории для данных +RUN mkdir -p /app/data/results /app/data/prompts /app/data/config \ + && chown -R ollama:ollama /app/data + +# Настройки по умолчанию +ENV LCG_PROVIDER=ollama +ENV LCG_HOST=http://127.0.0.1:11434/ +ENV LCG_MODEL=codegeex4 +ENV LCG_RESULT_FOLDER=/app/data/results +ENV LCG_PROMPT_FOLDER=/app/data/prompts +ENV LCG_CONFIG_FOLDER=/app/data/config +ENV LCG_SERVER_HOST=0.0.0.0 +ENV LCG_SERVER_PORT=8080 +ENV LCG_SERVER_ALLOW_HTTP=true +ENV OLLAMA_HOST=0.0.0.0 +ENV OLLAMA_PORT=11434 + +# Expose порты +EXPOSE 8080 11434 + +# Переключаемся на пользователя ollama +USER ollama + +WORKDIR /home/ollama + +# Запускаем entrypoint +ENTRYPOINT ["/entrypoint.sh"] +CMD [] + diff --git a/Dockerfiles/OllamaServer/Makefile b/Dockerfiles/OllamaServer/Makefile new file mode 100644 index 0000000..8e2b43c --- /dev/null +++ b/Dockerfiles/OllamaServer/Makefile @@ -0,0 +1,107 @@ +.PHONY: build build-podman run run-podman stop stop-podman logs logs-podman clean help + +# Переменные +IMAGE_NAME = lcg-ollama +IMAGE_TAG = latest +CONTAINER_NAME = lcg-ollama +DOCKERFILE = Dockerfile +CONTEXT = ../.. + +help: ## Показать справку + @echo "Доступные команды:" + @echo " make build - Собрать Docker образ" + @echo " make build-podman - Собрать Podman образ" + @echo " make run - Запустить контейнер (Docker)" + @echo " make run-podman - Запустить контейнер (Podman)" + @echo " make stop - Остановить контейнер (Docker)" + @echo " make stop-podman - Остановить контейнер (Podman)" + @echo " make logs - Показать логи (Docker)" + @echo " make logs-podman - Показать логи (Podman)" + @echo " make clean - Удалить контейнер и образ" + @echo " make compose-up - Запустить через docker-compose" + @echo " make compose-down - Остановить docker-compose" + @echo " make podman-compose-up - Запустить через podman-compose" + @echo " make podman-compose-down - Остановить podman-compose" + +build: ## Собрать Docker образ + docker build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) + @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" + +build-podman: ## Собрать Podman образ + podman build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) + @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" + +run: ## Запустить контейнер (Docker) + docker run -d \ + --name $(CONTAINER_NAME) \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + $(IMAGE_NAME):$(IMAGE_TAG) + @echo "Контейнер $(CONTAINER_NAME) запущен" + +run-podman: ## Запустить контейнер (Podman) + podman run -d \ + --name $(CONTAINER_NAME) \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + $(IMAGE_NAME):$(IMAGE_TAG) + @echo "Контейнер $(CONTAINER_NAME) запущен" + +stop: ## Остановить контейнер (Docker) + docker stop $(CONTAINER_NAME) || true + docker rm $(CONTAINER_NAME) || true + @echo "Контейнер $(CONTAINER_NAME) остановлен и удален" + +stop-podman: ## Остановить контейнер (Podman) + podman stop $(CONTAINER_NAME) || true + podman rm $(CONTAINER_NAME) || true + @echo "Контейнер $(CONTAINER_NAME) остановлен и удален" + +logs: ## Показать логи (Docker) + docker logs -f $(CONTAINER_NAME) + +logs-podman: ## Показать логи (Podman) + podman logs -f $(CONTAINER_NAME) + +clean: ## Удалить контейнер и образ + docker stop $(CONTAINER_NAME) || true + docker rm $(CONTAINER_NAME) || true + docker rmi $(IMAGE_NAME):$(IMAGE_TAG) || true + @echo "Контейнер и образ удалены" + +compose-up: ## Запустить через docker-compose + docker-compose up -d + @echo "Сервисы запущены через docker-compose" + +compose-down: ## Остановить docker-compose + docker-compose down + @echo "Сервисы остановлены" + +podman-compose-up: ## Запустить через podman-compose + podman-compose -f podman-compose.yml up -d + @echo "Сервисы запущены через podman-compose" + +podman-compose-down: ## Остановить podman-compose + podman-compose -f podman-compose.yml down + @echo "Сервисы остановлены" + +shell: ## Подключиться к контейнеру (Docker) + docker exec -it $(CONTAINER_NAME) sh + +shell-podman: ## Подключиться к контейнеру (Podman) + podman exec -it $(CONTAINER_NAME) sh + +pull-model: ## Загрузить модель codegeex4 (Docker) + docker exec $(CONTAINER_NAME) ollama pull codegeex4 + +pull-model-podman: ## Загрузить модель codegeex4 (Podman) + podman exec $(CONTAINER_NAME) ollama pull codegeex4 + diff --git a/Dockerfiles/OllamaServer/QUICKSTART.md b/Dockerfiles/OllamaServer/QUICKSTART.md new file mode 100644 index 0000000..bb8faa8 --- /dev/null +++ b/Dockerfiles/OllamaServer/QUICKSTART.md @@ -0,0 +1,172 @@ +# 🚀 Быстрый старт - LCG с Ollama + +## Подготовка + +1. Убедитесь, что у вас установлен Docker или Podman +2. Клонируйте репозиторий (если еще не сделали) +3. Перейдите в папку с Dockerfile + +```bash +cd Dockerfiles/OllamaServer +``` + +## Запуск с Docker + +### Вариант 1: Docker Compose (рекомендуется) + +```bash +docker-compose up -d +``` + +### Вариант 2: Ручная сборка и запуск + +```bash +# Сборка образа +docker build -f Dockerfile -t lcg-ollama:latest ../.. + +# Запуск контейнера +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + lcg-ollama:latest +``` + +## Запуск с Podman + +### Вариант 1: Podman Compose + +```bash +podman-compose -f podman-compose.yml up -d +``` + +### Вариант 2: Ручная сборка и запуск + +```bash +# Сборка образа +podman build -f Dockerfile -t lcg-ollama:latest ../.. + +# Запуск контейнера +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + lcg-ollama:latest +``` + +## Проверка запуска + +### Проверка логов + +```bash +# Docker +docker logs -f lcg-ollama + +# Podman +podman logs -f lcg-ollama +``` + +Дождитесь сообщений: +- `Ollama сервер готов!` +- `LCG сервер запущен на http://0.0.0.0:8080` + +### Проверка доступности + +```bash +# Проверка Ollama +curl http://localhost:11434/api/tags + +# Проверка LCG +curl http://localhost:8080/ +``` + +## Загрузка модели + +После запуска контейнера загрузите модель: + +```bash +# Docker +docker exec lcg-ollama ollama pull codegeex4 + +# Podman +podman exec lcg-ollama ollama pull codegeex4 +``` + +Или используйте модель по умолчанию, указанную в переменных окружения. + +## Доступ к веб-интерфейсу + +Откройте в браузере: http://localhost:8080 + +## Остановка + +```bash +# Docker +docker-compose down + +# Podman +podman-compose -f podman-compose.yml down +``` + +Или для ручного запуска: + +```bash +# Docker +docker stop lcg-ollama +docker rm lcg-ollama + +# Podman +podman stop lcg-ollama +podman rm lcg-ollama +``` + +## Решение проблем + +### Порт занят + +Измените порты в docker-compose.yml или команде run: + +```bash +-p 9000:8080 # LCG на порту 9000 +-p 11435:11434 # Ollama на порту 11435 +``` + +### Контейнер не запускается + +Проверьте логи: + +```bash +docker logs lcg-ollama +# или +podman logs lcg-ollama +``` + +### Модель не загружена + +Убедитесь, что модель существует: + +```bash +docker exec lcg-ollama ollama list +# или +podman exec lcg-ollama ollama list +``` + +Если модели нет, загрузите её: + +```bash +docker exec lcg-ollama ollama pull codegeex4 +# или +podman exec lcg-ollama ollama pull codegeex4 +``` + +## Следующие шаги + +- Прочитайте полную документацию в [README.md](README.md) +- Настройте аутентификацию для продакшена +- Настройте reverse proxy для HTTPS +- Загрузите нужные модели Ollama + diff --git a/Dockerfiles/OllamaServer/README.md b/Dockerfiles/OllamaServer/README.md new file mode 100644 index 0000000..1652453 --- /dev/null +++ b/Dockerfiles/OllamaServer/README.md @@ -0,0 +1,397 @@ +# 🐳 LCG с Ollama Server - Docker/Podman контейнер + +Этот образ содержит Linux Command GPT (LCG) и Ollama сервер, работающие вместе в одном контейнере. + +Поддерживается запуск через Docker и Podman. + +## 📋 Описание + +Контейнер автоматически запускает: +1. **Ollama сервер** (v0.9.5) на порту 11434 +2. **LCG веб-сервер** на порту 8080 + +Ollama используется как провайдер LLM для генерации Linux команд. + +## 🚀 Быстрый старт + +### Сборка образа + +#### Docker +```bash +# Из корня проекта +docker build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . +``` + +#### Podman +```bash +# Из корня проекта +podman build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . +``` + +### Запуск контейнера + +#### Docker +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Podman +```bash +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +### Использование docker-compose / podman-compose + +#### Docker Compose +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +#### Podman Compose +```bash +cd Dockerfiles/OllamaServer +podman-compose -f podman-compose.yml up -d +``` + +Или используйте встроенную поддержку Podman: +```bash +cd Dockerfiles/OllamaServer +podman play kube podman-compose.yml +``` + +## 🌐 Доступ к сервисам + +После запуска контейнера доступны: + +- **LCG веб-интерфейс**: http://localhost:8080 +- **Ollama API**: http://localhost:11434 + +## ⚙️ Переменные окружения + +### Настройки LCG + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `LCG_PROVIDER` | `ollama` | Тип провайдера | +| `LCG_HOST` | `http://127.0.0.1:11434/` | URL Ollama API | +| `LCG_MODEL` | `codegeex4` | Модель для использования | +| `LCG_SERVER_HOST` | `0.0.0.0` | Хост LCG сервера | +| `LCG_SERVER_PORT` | `8080` | Порт LCG сервера | +| `LCG_SERVER_ALLOW_HTTP` | `true` | Разрешить HTTP | +| `LCG_RESULT_FOLDER` | `/app/data/results` | Папка для результатов | +| `LCG_PROMPT_FOLDER` | `/app/data/prompts` | Папка для промптов | +| `LCG_CONFIG_FOLDER` | `/app/data/config` | Папка для конфигурации | + +### Настройки Ollama + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `OLLAMA_HOST` | `127.0.0.1` | Хост Ollama сервера | +| `OLLAMA_PORT` | `11434` | Порт Ollama сервера | + +### Безопасность + +| Переменная | Значение по умолчанию | Описание | +|------------|----------------------|----------| +| `LCG_SERVER_REQUIRE_AUTH` | `false` | Требовать аутентификацию | +| `LCG_SERVER_PASSWORD` | `admin#123456` | Пароль для аутентификации | + +## 📦 Volumes + +Рекомендуется монтировать volumes для персистентного хранения данных: + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -v ollama-data:/home/ollama/.ollama \ + -v lcg-results:/app/data/results \ + -v lcg-prompts:/app/data/prompts \ + -v lcg-config:/app/data/config \ + lcg-ollama:latest +``` + +### Volumes описание + +- `ollama-data`: Модели и данные Ollama +- `lcg-results`: Результаты генерации команд +- `lcg-prompts`: Системные промпты +- `lcg-config`: Конфигурация LCG + +## 🔧 Примеры использования + +### Запуск с кастомной моделью + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -e LCG_MODEL=llama3:8b \ + lcg-ollama:latest +``` + +### Запуск с аутентификацией + +```bash +docker run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + -e LCG_SERVER_REQUIRE_AUTH=true \ + -e LCG_SERVER_PASSWORD=my_secure_password \ + lcg-ollama:latest +``` + +### Запуск с кастомным портом + +```bash +docker run -d \ + --name lcg-ollama \ + -p 9000:9000 \ + -p 11434:11434 \ + -e LCG_SERVER_PORT=9000 \ + lcg-ollama:latest +``` + +## 📥 Загрузка моделей Ollama + +После запуска контейнера можно загрузить модели: + +```bash +# Подключиться к контейнеру +docker exec -it lcg-ollama sh + +# Загрузить модель +ollama pull codegeex4 +ollama pull llama3:8b +ollama pull qwen2.5:7b +``` + +Или извне контейнера: + +```bash +# Убедитесь, что Ollama доступен извне (OLLAMA_HOST=0.0.0.0) +docker exec lcg-ollama ollama pull codegeex4 +``` + +## 🔍 Проверка работоспособности + +### Проверка Ollama + +```bash +# Проверка health +curl http://localhost:11434/api/tags + +# Список моделей +curl http://localhost:11434/api/tags | jq '.models' +``` + +### Проверка LCG + +```bash +# Проверка веб-интерфейса +curl http://localhost:8080/ + +# Проверка через API +curl -X POST http://localhost:8080/api/execute \ + -H "Content-Type: application/json" \ + -d '{"prompt": "создать директорию test"}' +``` + +## 🐧 Podman специфичные инструкции + +### Запуск с Podman + +Podman работает аналогично Docker, но есть несколько отличий: + +#### Создание сетей (если нужно) + +```bash +podman network create lcg-network +``` + +#### Запуск с сетью + +```bash +podman run -d \ + --name lcg-ollama \ + --network lcg-network \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Запуск в rootless режиме + +Podman по умолчанию работает в rootless режиме, что повышает безопасность: + +```bash +# Не требует sudo +podman run -d \ + --name lcg-ollama \ + -p 8080:8080 \ + -p 11434:11434 \ + lcg-ollama:latest +``` + +#### Использование systemd для автозапуска + +Создайте systemd unit файл: + +```bash +# Генерируем unit файл +podman generate systemd --name lcg-ollama --files + +# Копируем в systemd +sudo cp container-lcg-ollama.service /etc/systemd/system/ + +# Включаем автозапуск +sudo systemctl enable container-lcg-ollama.service +sudo systemctl start container-lcg-ollama.service +``` + +#### Проверка статуса + +```bash +# Статус контейнера +podman ps + +# Логи +podman logs lcg-ollama + +# Логи в реальном времени +podman logs -f lcg-ollama +``` + +## 🐛 Отладка + +### Просмотр логов + +#### Docker +```bash +# Логи контейнера +docker logs lcg-ollama + +# Логи в реальном времени +docker logs -f lcg-ollama +``` + +#### Podman +```bash +# Логи контейнера +podman logs lcg-ollama + +# Логи в реальном времени +podman logs -f lcg-ollama +``` + +### Подключение к контейнеру + +#### Docker +```bash +docker exec -it lcg-ollama sh +``` + +#### Podman +```bash +podman exec -it lcg-ollama sh +``` + +### Проверка процессов + +#### Docker +```bash +docker exec lcg-ollama ps aux +``` + +#### Podman +```bash +podman exec lcg-ollama ps aux +``` + +## 🔒 Безопасность + +### Рекомендации для продакшена + +1. **Используйте аутентификацию**: + ```bash + -e LCG_SERVER_REQUIRE_AUTH=true + -e LCG_SERVER_PASSWORD=strong_password + ``` + +2. **Ограничьте доступ к портам**: + - Используйте firewall правила + - Не экспортируйте порты на публичный интерфейс + +3. **Используйте HTTPS**: + - Настройте reverse proxy (nginx, traefik) + - Используйте SSL сертификаты + +4. **Ограничьте ресурсы**: + ```bash + docker run -d \ + --name lcg-ollama \ + --memory="4g" \ + --cpus="2" \ + lcg-ollama:latest + ``` + +## 📊 Мониторинг + +### Healthcheck + +Контейнер включает healthcheck, который проверяет доступность LCG сервера: + +```bash +docker inspect lcg-ollama | jq '.[0].State.Health' +``` + +### Метрики + +LCG предоставляет Prometheus метрики на `/metrics` endpoint (если включено). + +## 🚀 Production Deployment + +### С docker-compose + +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +### С Kubernetes + +Используйте манифесты из папки `deploy/` или `kustomize/`. + +## 📝 Примечания + +- Ollama версия: 0.9.5 +- LCG версия: см. VERSION.txt +- Минимальные требования: 2GB RAM, 2 CPU cores +- Рекомендуется: 4GB+ RAM для больших моделей + +## 🔗 Полезные ссылки + +- [Ollama документация](https://github.com/ollama/ollama) +- [LCG документация](../../docs/README.md) +- [LCG API Guide](../../docs/API_GUIDE.md) + +## ❓ Поддержка + +При возникновении проблем: +1. Проверьте логи: `docker logs lcg-ollama` +2. Проверьте переменные окружения +3. Убедитесь, что порты не заняты +4. Проверьте, что модели загружены в Ollama + diff --git a/Dockerfiles/OllamaServer/STRUCTURE.md b/Dockerfiles/OllamaServer/STRUCTURE.md new file mode 100644 index 0000000..4efc13e --- /dev/null +++ b/Dockerfiles/OllamaServer/STRUCTURE.md @@ -0,0 +1,111 @@ +# 📁 Структура проекта OllamaServer + +## Файлы + +``` +Dockerfiles/OllamaServer/ +├── Dockerfile # Multi-stage Dockerfile для сборки образа +├── entrypoint.sh # Скрипт запуска LCG и Ollama серверов +├── docker-compose.yml # Docker Compose конфигурация +├── podman-compose.yml # Podman Compose конфигурация +├── Makefile # Команды для сборки и запуска +├── README.md # Полная документация +├── QUICKSTART.md # Быстрый старт +├── STRUCTURE.md # Этот файл +├── .dockerignore # Исключения для Docker build +└── .gitignore # Исключения для Git +``` + +## Описание файлов + +### Dockerfile +Multi-stage Dockerfile, который: +1. Собирает бинарник LCG из исходного кода +2. Устанавливает Ollama 0.9.5 +3. Создает пользователя ollama +4. Настраивает рабочее окружение + +### entrypoint.sh +Скрипт запуска, который: +1. Запускает Ollama сервер в фоне +2. Ожидает готовности Ollama API +3. Запускает LCG сервер в фоне +4. Мониторит состояние процессов +5. Корректно обрабатывает сигналы завершения + +### docker-compose.yml / podman-compose.yml +Конфигурация для запуска через compose: +- Настройки портов +- Переменные окружения +- Volumes для персистентного хранения +- Healthcheck + +### Makefile +Удобные команды для: +- Сборки образа +- Запуска/остановки контейнера +- Просмотра логов +- Работы с compose + +### README.md +Полная документация с: +- Описанием функциональности +- Инструкциями по установке +- Настройками переменных окружения +- Примерами использования +- Решением проблем + +### QUICKSTART.md +Краткое руководство для быстрого старта. + +## Порты + +- **8080**: LCG веб-сервер +- **11434**: Ollama API + +## Volumes + +- `ollama-data`: Данные Ollama (модели) +- `lcg-results`: Результаты генерации команд +- `lcg-prompts`: Системные промпты +- `lcg-config`: Конфигурация LCG + +## Переменные окружения + +Основные переменные (см. README.md для полного списка): +- `LCG_PROVIDER=ollama` +- `LCG_HOST=http://127.0.0.1:11434/` +- `LCG_MODEL=codegeex4` +- `OLLAMA_HOST=0.0.0.0` +- `OLLAMA_PORT=11434` + +## Запуск + +### Docker +```bash +cd Dockerfiles/OllamaServer +docker-compose up -d +``` + +### Podman +```bash +cd Dockerfiles/OllamaServer +podman-compose -f podman-compose.yml up -d +``` + +### Make +```bash +cd Dockerfiles/OllamaServer +make compose-up +# или +make podman-compose-up +``` + +## Архитектура + +Контейнер запускает два сервиса: +1. **Ollama** (порт 11434) - LLM сервер +2. **LCG** (порт 8080) - Веб-интерфейс и API + +Оба сервиса работают в одном контейнере и общаются через localhost. + diff --git a/Dockerfiles/OllamaServer/docker-compose.yml b/Dockerfiles/OllamaServer/docker-compose.yml new file mode 100644 index 0000000..ca76825 --- /dev/null +++ b/Dockerfiles/OllamaServer/docker-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + lcg-ollama: + build: + context: ../.. + dockerfile: Dockerfiles/OllamaServer/Dockerfile + container_name: lcg-ollama + ports: + - "8080:8080" # LCG веб-сервер + - "11434:11434" # Ollama API + environment: + # Настройки LCG + - LCG_PROVIDER=ollama + - LCG_HOST=http://127.0.0.1:11434/ + - LCG_MODEL=codegeex4 + - LCG_RESULT_FOLDER=/app/data/results + - LCG_PROMPT_FOLDER=/app/data/prompts + - LCG_CONFIG_FOLDER=/app/data/config + - LCG_SERVER_HOST=0.0.0.0 + - LCG_SERVER_PORT=8080 + - LCG_SERVER_ALLOW_HTTP=true + # Настройки Ollama + - OLLAMA_HOST=0.0.0.0 + - OLLAMA_PORT=11434 + - OLLAMA_ORIGINS=* + # Опционально: настройки безопасности + - LCG_SERVER_REQUIRE_AUTH=false + - LCG_SERVER_PASSWORD=admin#123456 + volumes: + # Персистентное хранилище для данных Ollama + - ollama-data:/home/ollama/.ollama + # Персистентное хранилище для результатов LCG + - lcg-results:/app/data/results + - lcg-prompts:/app/data/prompts + - lcg-config:/app/data/config + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +volumes: + ollama-data: + driver: local + lcg-results: + driver: local + lcg-prompts: + driver: local + lcg-config: + driver: local + diff --git a/Dockerfiles/OllamaServer/entrypoint.sh b/Dockerfiles/OllamaServer/entrypoint.sh new file mode 100755 index 0000000..f7b6f97 --- /dev/null +++ b/Dockerfiles/OllamaServer/entrypoint.sh @@ -0,0 +1,171 @@ +#!/bin/bash +set -e + +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Функция для логирования +log() { + echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" >&2 +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Обработка сигналов для корректного завершения +cleanup() { + log "Получен сигнал завершения, останавливаем сервисы..." + if [ ! -z "$LCG_PID" ]; then + kill $LCG_PID 2>/dev/null || true + wait $LCG_PID 2>/dev/null || true + fi + if [ ! -z "$OLLAMA_PID" ]; then + kill $OLLAMA_PID 2>/dev/null || true + wait $OLLAMA_PID 2>/dev/null || true + fi + log "Сервисы остановлены" + exit 0 +} + +trap cleanup SIGTERM SIGINT + +# Проверка наличия бинарника lcg +if [ ! -f /usr/local/bin/lcg ]; then + error "Бинарник lcg не найден в /usr/local/bin/lcg" + exit 1 +fi + +# Проверка наличия Ollama +if [ ! -f /usr/local/bin/ollama ]; then + error "Ollama не найден в /usr/local/bin/ollama" + exit 1 +fi + +# Создаем необходимые директории +mkdir -p "${LCG_RESULT_FOLDER:-/app/data/results}" +mkdir -p "${LCG_PROMPT_FOLDER:-/app/data/prompts}" +mkdir -p "${LCG_CONFIG_FOLDER:-/app/data/config}" + +# Настройка переменных окружения для Ollama +export OLLAMA_HOST="${OLLAMA_HOST:-0.0.0.0}" +export OLLAMA_PORT="${OLLAMA_PORT:-11434}" +export OLLAMA_ORIGINS="*" + +# Настройка переменных окружения для LCG +export LCG_PROVIDER="${LCG_PROVIDER:-ollama}" +export LCG_HOST="${LCG_HOST:-http://127.0.0.1:11434/}" +export LCG_MODEL="${LCG_MODEL:-codegeex4}" +export LCG_RESULT_FOLDER="${LCG_RESULT_FOLDER:-/app/data/results}" +export LCG_PROMPT_FOLDER="${LCG_PROMPT_FOLDER:-/app/data/prompts}" +export LCG_CONFIG_FOLDER="${LCG_CONFIG_FOLDER:-/app/data/config}" +export LCG_SERVER_HOST="${LCG_SERVER_HOST:-0.0.0.0}" +export LCG_SERVER_PORT="${LCG_SERVER_PORT:-8080}" +export LCG_SERVER_ALLOW_HTTP="${LCG_SERVER_ALLOW_HTTP:-true}" + +log "==========================================" +log "Запуск LCG с Ollama сервером" +log "==========================================" +info "LCG Provider: $LCG_PROVIDER" +info "LCG Host: $LCG_HOST" +info "LCG Model: $LCG_MODEL" +info "LCG Server: http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" +info "Ollama Host: $OLLAMA_HOST:$OLLAMA_PORT" +log "==========================================" + +# Запускаем Ollama сервер в фоне +log "Запуск Ollama сервера..." +/usr/local/bin/ollama serve & +OLLAMA_PID=$! + +# Ждем, пока Ollama запустится +log "Ожидание запуска Ollama сервера..." +sleep 5 + +# Проверяем, что Ollama запущен +if ! kill -0 $OLLAMA_PID 2>/dev/null; then + error "Ollama сервер не запустился" + exit 1 +fi + +# Проверяем доступность Ollama API +max_attempts=30 +attempt=0 +while [ $attempt -lt $max_attempts ]; do + # Проверяем через localhost, так как OLLAMA_HOST может быть 0.0.0.0 + if curl -s -f "http://127.0.0.1:${OLLAMA_PORT}/api/tags" > /dev/null 2>&1; then + log "Ollama сервер готов!" + break + fi + attempt=$((attempt + 1)) + if [ $attempt -eq $max_attempts ]; then + error "Ollama сервер не отвечает после $max_attempts попыток" + exit 1 + fi + sleep 1 +done + +# Запускаем LCG сервер в фоне +log "Запуск LCG сервера..." +/usr/local/bin/lcg serve \ + --host "${LCG_SERVER_HOST}" \ + --port "${LCG_SERVER_PORT}" & +LCG_PID=$! + +# Ждем, пока LCG запустится +sleep 3 + +# Проверяем, что LCG запущен +if ! kill -0 $LCG_PID 2>/dev/null; then + error "LCG сервер не запустился" + kill $OLLAMA_PID 2>/dev/null || true + exit 1 +fi + +log "LCG сервер запущен на http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" +log "Ollama сервер доступен на http://${OLLAMA_HOST}:${OLLAMA_PORT}" +log "==========================================" +log "Сервисы запущены и готовы к работе!" +log "==========================================" + +# Функция для проверки здоровья процессов +health_check() { + while true; do + # Проверяем Ollama + if ! kill -0 $OLLAMA_PID 2>/dev/null; then + error "Ollama процесс завершился неожиданно" + kill $LCG_PID 2>/dev/null || true + exit 1 + fi + + # Проверяем LCG + if ! kill -0 $LCG_PID 2>/dev/null; then + error "LCG процесс завершился неожиданно" + kill $OLLAMA_PID 2>/dev/null || true + exit 1 + fi + + sleep 10 + done +} + +# Запускаем проверку здоровья в фоне +health_check & +HEALTH_CHECK_PID=$! + +# Ждем завершения процессов +wait $LCG_PID $OLLAMA_PID +kill $HEALTH_CHECK_PID 2>/dev/null || true + diff --git a/Dockerfiles/OllamaServer/podman-compose.yml b/Dockerfiles/OllamaServer/podman-compose.yml new file mode 100644 index 0000000..ca76825 --- /dev/null +++ b/Dockerfiles/OllamaServer/podman-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + lcg-ollama: + build: + context: ../.. + dockerfile: Dockerfiles/OllamaServer/Dockerfile + container_name: lcg-ollama + ports: + - "8080:8080" # LCG веб-сервер + - "11434:11434" # Ollama API + environment: + # Настройки LCG + - LCG_PROVIDER=ollama + - LCG_HOST=http://127.0.0.1:11434/ + - LCG_MODEL=codegeex4 + - LCG_RESULT_FOLDER=/app/data/results + - LCG_PROMPT_FOLDER=/app/data/prompts + - LCG_CONFIG_FOLDER=/app/data/config + - LCG_SERVER_HOST=0.0.0.0 + - LCG_SERVER_PORT=8080 + - LCG_SERVER_ALLOW_HTTP=true + # Настройки Ollama + - OLLAMA_HOST=0.0.0.0 + - OLLAMA_PORT=11434 + - OLLAMA_ORIGINS=* + # Опционально: настройки безопасности + - LCG_SERVER_REQUIRE_AUTH=false + - LCG_SERVER_PASSWORD=admin#123456 + volumes: + # Персистентное хранилище для данных Ollama + - ollama-data:/home/ollama/.ollama + # Персистентное хранилище для результатов LCG + - lcg-results:/app/data/results + - lcg-prompts:/app/data/prompts + - lcg-config:/app/data/config + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +volumes: + ollama-data: + driver: local + lcg-results: + driver: local + lcg-prompts: + driver: local + lcg-config: + driver: local + diff --git a/VERSION.txt b/VERSION.txt index 68496c0..0e18aae 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -v2.0.14 +v2.0.15 diff --git a/deploy/VERSION.txt b/deploy/VERSION.txt index 68496c0..0e18aae 100644 --- a/deploy/VERSION.txt +++ b/deploy/VERSION.txt @@ -1 +1 @@ -v2.0.14 +v2.0.15 diff --git a/docs/CONFIG_COMMAND.md b/docs/CONFIG_COMMAND.md index 1b35f76..70ef9af 100644 --- a/docs/CONFIG_COMMAND.md +++ b/docs/CONFIG_COMMAND.md @@ -69,8 +69,8 @@ lcg co -f "host": "localhost" }, "validation": { - "max_system_prompt_length": 1000, - "max_user_message_length": 2000, + "max_system_prompt_length": 2000, + "max_user_message_length": 4000, "max_prompt_name_length": 2000, "max_prompt_desc_length": 5000, "max_command_length": 8000, @@ -116,12 +116,12 @@ lcg co -f ### Настройки валидации (validation) -- **max_system_prompt_length** - максимальная длина системного промпта -- **max_user_message_length** - максимальная длина пользовательского сообщения -- **max_prompt_name_length** - максимальная длина названия промпта -- **max_prompt_desc_length** - максимальная длина описания промпта -- **max_command_length** - максимальная длина команды/ответа -- **max_explanation_length** - максимальная длина объяснения +- **max_system_prompt_length** - максимальная длина системного промпта (по умолчанию: 2000) +- **max_user_message_length** - максимальная длина пользовательского сообщения (по умолчанию: 4000) +- **max_prompt_name_length** - максимальная длина названия промпта (по умолчанию: 2000) +- **max_prompt_desc_length** - максимальная длина описания промпта (по умолчанию: 5000) +- **max_command_length** - максимальная длина команды/ответа (по умолчанию: 8000) +- **max_explanation_length** - максимальная длина объяснения (по умолчанию: 20000) ## 🔒 Безопасность diff --git a/docs/README.md b/docs/README.md index 05eec33..d5bcf78 100644 --- a/docs/README.md +++ b/docs/README.md @@ -35,10 +35,17 @@ Explanations: Clipboard support requires `xclip` or `xsel`. -## What's new in 2.0.1 +## What's new in 2.0.14 -- Mobile UI improvements: better responsiveness (buttons, fonts, spacing) and reduced motion support -- Public REST endpoint: `POST /execute` (curl-only) for programmatic access — see `API_GUIDE.md` +- Authentication: JWT-based authentication with HTTP-only cookies +- CSRF protection: Full CSRF protection with tokens and middleware +- Security: Enhanced security with token validation and sessions +- Kubernetes deployment: Full set of manifests for Kubernetes deployment with Traefik +- Reverse Proxy: Support for working behind reverse proxy with cookie configuration +- Web interface: Improved web interface with modern design +- Monitoring: Prometheus metrics and ServiceMonitor +- Scaling: HPA for automatic scaling +- Testing: CSRF protection testing tools ## Environment diff --git a/docs/USAGE_GUIDE.md b/docs/USAGE_GUIDE.md index 4c74dc8..c408c51 100644 --- a/docs/USAGE_GUIDE.md +++ b/docs/USAGE_GUIDE.md @@ -22,7 +22,7 @@ sudo apt-get install xsel ```bash -git clone --depth 1 https://github.com/Direct-Dev-Ru/go-lcg.git ~/.linux-command-gpt +git clone --depth 1 https://github.com/Direct-Dev-Ru/linux-command-gpt.git ~/.linux-command-gpt cd ~/.linux-command-gpt go build -o lcg @@ -60,7 +60,7 @@ lcg --file /path/to/context.txt "хочу вывести список дирек Действия: (c)копировать, (s)сохранить, (r)перегенерировать, (e)выполнить, (v|vv|vvv)подробно, (n)ничего: ``` -### Что нового в 3.0.0 +### Что нового в 2.0.14 - **Аутентификация**: Добавлена система аутентификации с JWT токенами и HTTP-only cookies - **CSRF защита**: Полная защита от CSRF атак с токенами и middleware diff --git a/docs/VALIDATION_CONFIG.md b/docs/VALIDATION_CONFIG.md index e1f2d9d..de88b96 100644 --- a/docs/VALIDATION_CONFIG.md +++ b/docs/VALIDATION_CONFIG.md @@ -8,26 +8,26 @@ | Переменная | Описание | По умолчанию | |------------|----------|--------------| -| `LCG_MAX_SYSTEM_PROMPT_LENGTH` | Максимальная длина системного промпта | 1000 | -| `LCG_MAX_USER_MESSAGE_LENGTH` | Максимальная длина пользовательского сообщения | 2000 | -| `LCG_MAX_PROMPT_NAME_LENGTH` | Максимальная длина названия промпта | 200 | -| `LCG_MAX_PROMPT_DESC_LENGTH` | Максимальная длина описания промпта | 500 | -| `LCG_MAX_COMMAND_LENGTH` | Максимальная длина команды/ответа | 2000 | -| `LCG_MAX_EXPLANATION_LENGTH` | Максимальная длина объяснения | 2000 | +| `LCG_MAX_SYSTEM_PROMPT_LENGTH` | Максимальная длина системного промпта | 2000 | +| `LCG_MAX_USER_MESSAGE_LENGTH` | Максимальная длина пользовательского сообщения | 4000 | +| `LCG_MAX_PROMPT_NAME_LENGTH` | Максимальная длина названия промпта | 2000 | +| `LCG_MAX_PROMPT_DESC_LENGTH` | Максимальная длина описания промпта | 5000 | +| `LCG_MAX_COMMAND_LENGTH` | Максимальная длина команды/ответа | 8000 | +| `LCG_MAX_EXPLANATION_LENGTH` | Максимальная длина объяснения | 20000 | ## 🚀 Примеры использования ### Установка через переменные окружения ```bash -# Увеличить лимит системного промпта до 2к символов -export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 +# Увеличить лимит системного промпта до 3к символов +export LCG_MAX_SYSTEM_PROMPT_LENGTH=3000 -# Уменьшить лимит пользовательского сообщения до 1к символов -export LCG_MAX_USER_MESSAGE_LENGTH=1000 +# Уменьшить лимит пользовательского сообщения до 2к символов +export LCG_MAX_USER_MESSAGE_LENGTH=2000 -# Увеличить лимит названия промпта до 500 символов -export LCG_MAX_PROMPT_NAME_LENGTH=500 +# Увеличить лимит названия промпта до 3000 символов +export LCG_MAX_PROMPT_NAME_LENGTH=3000 ``` ### Установка в .env файле @@ -35,11 +35,11 @@ export LCG_MAX_PROMPT_NAME_LENGTH=500 ```bash # .env файл LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -LCG_MAX_USER_MESSAGE_LENGTH=1500 -LCG_MAX_PROMPT_NAME_LENGTH=300 -LCG_MAX_PROMPT_DESC_LENGTH=1000 -LCG_MAX_COMMAND_LENGTH=3000 -LCG_MAX_EXPLANATION_LENGTH=5000 +LCG_MAX_USER_MESSAGE_LENGTH=4000 +LCG_MAX_PROMPT_NAME_LENGTH=2000 +LCG_MAX_PROMPT_DESC_LENGTH=5000 +LCG_MAX_COMMAND_LENGTH=8000 +LCG_MAX_EXPLANATION_LENGTH=20000 ``` ### Установка в systemd сервисе @@ -55,8 +55,8 @@ User=lcg WorkingDirectory=/opt/lcg ExecStart=/opt/lcg/lcg serve Environment=LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -Environment=LCG_MAX_USER_MESSAGE_LENGTH=1500 -Environment=LCG_MAX_PROMPT_NAME_LENGTH=300 +Environment=LCG_MAX_USER_MESSAGE_LENGTH=4000 +Environment=LCG_MAX_PROMPT_NAME_LENGTH=2000 Restart=always [Install] @@ -72,7 +72,7 @@ FROM golang:1.21-alpine AS builder FROM alpine:latest COPY --from=builder /app/lcg /usr/local/bin/ ENV LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -ENV LCG_MAX_USER_MESSAGE_LENGTH=1500 +ENV LCG_MAX_USER_MESSAGE_LENGTH=4000 CMD ["lcg", "serve"] ``` @@ -84,8 +84,8 @@ services: image: lcg:latest environment: - LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 - - LCG_MAX_USER_MESSAGE_LENGTH=1500 - - LCG_MAX_PROMPT_NAME_LENGTH=300 + - LCG_MAX_USER_MESSAGE_LENGTH=4000 + - LCG_MAX_PROMPT_NAME_LENGTH=2000 ports: - "8080:8080" ``` @@ -153,9 +153,9 @@ validation.FormatLengthInfo(systemPrompt, userMessage) ## 📝 Примеры сообщений об ошибках ``` -❌ Ошибка: system_prompt: системный промпт слишком длинный: 1500 символов (максимум 1000) -❌ Ошибка: user_message: пользовательское сообщение слишком длинное: 2500 символов (максимум 2000) -❌ Ошибка: prompt_name: название промпта слишком длинное: 300 символов (максимум 200) +❌ Ошибка: system_prompt: системный промпт слишком длинный: 2500 символов (максимум 2000) +❌ Ошибка: user_message: пользовательское сообщение слишком длинное: 4500 символов (максимум 4000) +❌ Ошибка: prompt_name: название промпта слишком длинное: 2500 символов (максимум 2000) ``` ## 🔄 Миграция с жестко заданных значений @@ -179,25 +179,25 @@ if err := validation.ValidateSystemPrompt(prompt); err != nil { ### Для разработки ```bash export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 -export LCG_MAX_USER_MESSAGE_LENGTH=2000 -export LCG_MAX_PROMPT_NAME_LENGTH=200 -export LCG_MAX_PROMPT_DESC_LENGTH=500 +export LCG_MAX_USER_MESSAGE_LENGTH=4000 +export LCG_MAX_PROMPT_NAME_LENGTH=2000 +export LCG_MAX_PROMPT_DESC_LENGTH=5000 ``` ### Для продакшена ```bash -export LCG_MAX_SYSTEM_PROMPT_LENGTH=1000 -export LCG_MAX_USER_MESSAGE_LENGTH=1500 -export LCG_MAX_PROMPT_NAME_LENGTH=100 -export LCG_MAX_PROMPT_DESC_LENGTH=300 +export LCG_MAX_SYSTEM_PROMPT_LENGTH=2000 +export LCG_MAX_USER_MESSAGE_LENGTH=4000 +export LCG_MAX_PROMPT_NAME_LENGTH=2000 +export LCG_MAX_PROMPT_DESC_LENGTH=5000 ``` ### Для высоконагруженных систем ```bash -export LCG_MAX_SYSTEM_PROMPT_LENGTH=500 -export LCG_MAX_USER_MESSAGE_LENGTH=1000 -export LCG_MAX_PROMPT_NAME_LENGTH=50 -export LCG_MAX_PROMPT_DESC_LENGTH=200 +export LCG_MAX_SYSTEM_PROMPT_LENGTH=1000 +export LCG_MAX_USER_MESSAGE_LENGTH=2000 +export LCG_MAX_PROMPT_NAME_LENGTH=1000 +export LCG_MAX_PROMPT_DESC_LENGTH=2500 ``` --- diff --git a/main.go b/main.go index 114314f..eb86f93 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func main() { CompileConditions.NoServe = false } - fmt.Println("Build conditions:", CompileConditions) + // fmt.Println("Build conditions:", CompileConditions) _ = colorBlue @@ -87,12 +87,56 @@ lcg [опции] <описание команды> {{.AppName}} - инструмент для генерации Linux команд из описаний на естественном языке. Поддерживает чтение частей промпта из файлов и позволяет сохранять, копировать или перегенерировать результаты. может задавать системный промпт или выбирать из предустановленных промптов. + Переменные окружения: - LCG_HOST Endpoint для LLM API (по умолчанию: http://192.168.87.108:11434/) - LCG_MODEL Название модели (по умолчанию: codegeex4) - LCG_PROMPT Текст промпта по умолчанию - LCG_PROVIDER Тип провайдера: "ollama" или "proxy" (по умолчанию: ollama) - LCG_JWT_TOKEN JWT токен для proxy провайдера + +Основные настройки: + LCG_HOST Endpoint для LLM API (по умолчанию: http://192.168.87.108:11434/) + LCG_MODEL Название модели (по умолчанию: hf.co/yandex/YandexGPT-5-Lite-8B-instruct-GGUF:Q4_K_M) + LCG_PROMPT Текст промпта по умолчанию + LCG_PROVIDER Тип провайдера: "ollama" или "proxy" (по умолчанию: ollama) + LCG_JWT_TOKEN JWT токен для proxy провайдера + LCG_PROMPT_ID ID промпта по умолчанию (по умолчанию: 1) + LCG_TIMEOUT Таймаут запроса в секундах (по умолчанию: 300) + LCG_COMPLETIONS_PATH Путь к API для завершений (по умолчанию: api/chat) + LCG_PROXY_URL URL прокси для proxy провайдера (по умолчанию: /api/v1/protected/sberchat/chat) + LCG_API_KEY_FILE Файл с API ключом (по умолчанию: .openai_api_key) + LCG_APP_NAME Название приложения (по умолчанию: Linux Command GPT) + +Настройки истории и выполнения: + LCG_NO_HISTORY Отключить запись истории ("1" или "true" = отключено, пусто = включено) + LCG_ALLOW_EXECUTION Разрешить выполнение команд ("1" или "true" = разрешено, пусто = запрещено) + LCG_RESULT_FOLDER Папка для сохранения результатов (по умолчанию: ~/.config/lcg/gpt_results) + LCG_RESULT_HISTORY Файл истории результатов (по умолчанию: /lcg_history.json) + LCG_PROMPT_FOLDER Папка для системных промптов (по умолчанию: ~/.config/lcg/gpt_sys_prompts) + LCG_CONFIG_FOLDER Папка для конфигурации (по умолчанию: ~/.config/lcg/config) + +Настройки сервера (команда serve): + LCG_SERVER_PORT Порт сервера (по умолчанию: 8080) + LCG_SERVER_HOST Хост сервера (по умолчанию: localhost) + LCG_SERVER_ALLOW_HTTP Разрешить HTTP соединения ("true" для localhost, "false" для других хостов) + LCG_SERVER_REQUIRE_AUTH Требовать аутентификацию ("1" или "true" = требуется, пусто = не требуется) + LCG_SERVER_PASSWORD Пароль администратора (по умолчанию: admin#123456) + LCG_SERVER_SSL_CERT_FILE Путь к SSL сертификату + LCG_SERVER_SSL_KEY_FILE Путь к приватному ключу SSL + LCG_DOMAIN Домен для сервера (по умолчанию: значение LCG_SERVER_HOST) + LCG_COOKIE_SECURE Безопасные cookie ("1" или "true" = включено, пусто = выключено) + LCG_COOKIE_PATH Путь для cookie (по умолчанию: /lcg) + LCG_COOKIE_TTL_HOURS Время жизни cookie в часах (по умолчанию: 168) + LCG_BASE_URL Базовый URL приложения (по умолчанию: /lcg) + LCG_HEALTH_URL URL для проверки здоровья API (по умолчанию: /api/v1/protected/sberchat/health) + +Настройки валидации: + LCG_MAX_SYSTEM_PROMPT_LENGTH Максимальная длина системного промпта (по умолчанию: 2000) + LCG_MAX_USER_MESSAGE_LENGTH Максимальная длина пользовательского сообщения (по умолчанию: 4000) + LCG_MAX_PROMPT_NAME_LENGTH Максимальная длина названия промпта (по умолчанию: 2000) + LCG_MAX_PROMPT_DESC_LENGTH Максимальная длина описания промпта (по умолчанию: 5000) + LCG_MAX_COMMAND_LENGTH Максимальная длина команды (по умолчанию: 8000) + LCG_MAX_EXPLANATION_LENGTH Максимальная длина объяснения (по умолчанию: 20000) + +Отладка и браузер: + LCG_DEBUG Включить режим отладки ("1" или "true" = включено, пусто = выключено) + LCG_BROWSER_PATH Путь к браузеру для автоматического открытия (команда serve --browser) `, Flags: []cli.Flag{ &cli.StringFlag{ @@ -159,8 +203,8 @@ lcg [опции] <описание команды> config.AppConfig.MainFlags.Debug = config.AppConfig.MainFlags.Debug || config.GetEnvBool("LCG_DEBUG", false) - fmt.Println("Debug:", config.AppConfig.MainFlags.Debug) - fmt.Println("LCG_DEBUG:", config.GetEnvBool("LCG_DEBUG", false)) + // fmt.Println("Debug:", config.AppConfig.MainFlags.Debug) + // fmt.Println("LCG_DEBUG:", config.GetEnvBool("LCG_DEBUG", false)) args := c.Args().Slice() diff --git a/serve/serve.go b/serve/serve.go index f05dd78..d0d8244 100644 --- a/serve/serve.go +++ b/serve/serve.go @@ -232,11 +232,11 @@ func registerRoutesExceptHome() { http.HandleFunc(makePath("/api/add-to-history"), AuthMiddleware(CSRFMiddleware(handleAddToHistory))) // Catch-all 404 для любых незарегистрированных путей (только когда BasePath задан) - if getBasePath() != "" { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - renderNotFound(w, "Страница не найдена", getBasePath()) - }) - } + // if getBasePath() != "" { + // http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + // renderNotFound(w, "Страница не найдена", getBasePath()) + // }) + // } } // registerRoutes регистрирует все маршруты сервера diff --git a/serve/templates/not_found.go b/serve/templates/not_found.go index 09296d0..99c90f4 100644 --- a/serve/templates/not_found.go +++ b/serve/templates/not_found.go @@ -53,6 +53,16 @@ const NotFoundTemplate = ` backdrop-filter: blur(10px); text-align: center; } + @keyframes pulse { + 0%, 100% { + transform: scale(1); + text-shadow: 0 8px 40px var(--accentGlow); + } + 50% { + transform: scale(1.15); + text-shadow: 0 12px 60px var(--accentGlow), 0 0 30px var(--accentGlow2); + } + } .code { font-size: clamp(48px, 12vw, 120px); line-height: 0.9; @@ -64,6 +74,8 @@ const NotFoundTemplate = ` color: transparent; margin: 8px 0 12px 0; text-shadow: 0 8px 40px var(--accentGlow); + animation: pulse 2.5s ease-in-out infinite; + transform-origin: center; } .title { font-size: clamp(18px, 3.2vw, 28px); @@ -133,7 +145,7 @@ const NotFoundTemplate = `
404
Страница не найдена
-

{{.Message}}

+

Такой страницы не существует. Вы можете вернуться на главную страницу или выполнить команду.

🏠 На главную 🚀 К выполнению @@ -143,5 +155,3 @@ const NotFoundTemplate = ` ` - - From c975e00c50d7cf294920f54741e62bc31c6fe7fb Mon Sep 17 00:00:00 2001 From: Anton Kuznetcov Date: Sun, 9 Nov 2025 12:47:23 +0600 Subject: [PATCH 6/6] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=B2=D0=B5=D1=82=D0=BA?= =?UTF-8?q?=D0=B5=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfiles/OllamaServer/Dockerfile | 109 ++++++++++---------- Dockerfiles/OllamaServer/Makefile | 17 ++- Dockerfiles/OllamaServer/QUICKSTART.md | 23 ++++- Dockerfiles/OllamaServer/README.md | 95 +++++++++++++---- Dockerfiles/OllamaServer/STRUCTURE.md | 48 +++++++-- Dockerfiles/OllamaServer/docker-compose.yml | 3 +- Dockerfiles/OllamaServer/entrypoint.sh | 80 +------------- VERSION.txt | 2 +- config/config.go | 1 + deploy/VERSION.txt | 2 +- kustomize/configmap.yaml | 2 +- kustomize/deployment.yaml | 4 +- kustomize/kustomization.yaml | 4 +- main.go | 80 +++++++++++--- 14 files changed, 288 insertions(+), 182 deletions(-) diff --git a/Dockerfiles/OllamaServer/Dockerfile b/Dockerfiles/OllamaServer/Dockerfile index 6a73f6f..34c7949 100644 --- a/Dockerfiles/OllamaServer/Dockerfile +++ b/Dockerfiles/OllamaServer/Dockerfile @@ -1,74 +1,79 @@ -# Multi-stage build для LCG с Ollama -FROM golang:1.24.6-alpine3.22 AS builder +# Используем готовый образ Ollama +FROM localhost/ollama_packed:latest -WORKDIR /build +# Устанавливаем bash если его нет (базовый образ ollama может быть на разных дистрибутивах) +RUN if ! command -v bash >/dev/null 2>&1; then \ + if command -v apk >/dev/null 2>&1; then \ + apk add --no-cache bash; \ + elif command -v apt-get >/dev/null 2>&1; then \ + apt-get update && apt-get install -y --no-install-recommends bash && rm -rf /var/lib/apt/lists/*; \ + fi; \ + fi -# Копируем файлы зависимостей -COPY go.mod go.sum ./ -RUN go mod download - -# Копируем исходный код -COPY . . - -# Собираем бинарник -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s -buildid=" -trimpath -o /build/lcg . - -# Финальный образ с Ollama -FROM alpine:3.22 - -# Устанавливаем необходимые пакеты -RUN apk add --no-cache \ - curl \ - ca-certificates \ - bash \ - && rm -rf /var/cache/apk/* - -# Устанавливаем Ollama 0.9.5 (поддержка разных архитектур) +# Определяем архитектуру для копирования правильного бинарника ARG TARGETARCH -RUN case ${TARGETARCH} in \ - amd64) OLLAMA_ARCH=amd64 ;; \ - arm64) OLLAMA_ARCH=arm64 ;; \ - arm) OLLAMA_ARCH=arm64 ;; \ - *) echo "Unsupported architecture: ${TARGETARCH}" && exit 1 ;; \ +ARG TARGETOS=linux + +# Копируем папку dist с бинарниками +# Структура: dist/lcg_linux_amd64_v1/lcg_* или dist/lcg_linux_arm64_v8.0/lcg_* +COPY dist/ /tmp/dist/ + +# Выбираем правильный бинарник в зависимости от архитектуры +# Если TARGETARCH не установлен, определяем архитектуру через uname +RUN ARCH="${TARGETARCH:-$(uname -m)}" && \ + case "${ARCH}" in \ + amd64|x86_64) \ + BIN_FILE=$(find /tmp/dist/lcg_linux_amd64_v* -name "lcg_*" -type f 2>/dev/null | head -1) && \ + if [ -n "$BIN_FILE" ]; then \ + cp "$BIN_FILE" /usr/local/bin/lcg && \ + echo "Установлен бинарник для amd64: $BIN_FILE"; \ + else \ + echo "Бинарник для amd64 не найден в /tmp/dist/" && exit 1; \ + fi ;; \ + arm64|aarch64|arm) \ + BIN_FILE=$(find /tmp/dist/lcg_linux_arm64_v* -name "lcg_*" -type f 2>/dev/null | head -1) && \ + if [ -n "$BIN_FILE" ]; then \ + cp "$BIN_FILE" /usr/local/bin/lcg && \ + echo "Установлен бинарник для arm64: $BIN_FILE"; \ + else \ + echo "Бинарник для arm64 не найден в /tmp/dist/" && exit 1; \ + fi ;; \ + *) \ + echo "Unsupported architecture: ${ARCH}" && \ + echo "Доступные бинарники:" && \ + find /tmp/dist -name "lcg_*" -type f 2>/dev/null && \ + exit 1 ;; \ esac && \ - curl -L https://github.com/ollama/ollama/releases/download/v0.9.5/ollama-linux-${OLLAMA_ARCH} -o /usr/local/bin/ollama \ - && chmod +x /usr/local/bin/ollama - -# Создаем пользователя для запуска сервисов -RUN addgroup -g 1000 ollama && \ - adduser -D -u 1000 -G ollama ollama && \ - mkdir -p /home/ollama/.ollama && \ - chown -R ollama:ollama /home/ollama - -# Копируем бинарник lcg -COPY --from=builder /build/lcg /usr/local/bin/lcg -RUN chmod +x /usr/local/bin/lcg + chmod +x /usr/local/bin/lcg && \ + rm -rf /tmp/dist && \ + (lcg --version || echo "Бинарник lcg установлен") # Копируем entrypoint скрипт COPY --chmod=755 Dockerfiles/OllamaServer/entrypoint.sh /entrypoint.sh -# Создаем директории для данных -RUN mkdir -p /app/data/results /app/data/prompts /app/data/config \ - && chown -R ollama:ollama /app/data +# Создаем директории для данных LCG +# В базовом образе ollama уже есть пользователь ollama +RUN mkdir -p /app/data/results /app/data/prompts /app/data/config + +# Устанавливаем права доступа (пользователь ollama должен существовать в базовом образе) +RUN chown -R ollama:ollama /app/data 2>/dev/null || \ + (chown -R 1000:1000 /app/data 2>/dev/null || true) # Настройки по умолчанию ENV LCG_PROVIDER=ollama ENV LCG_HOST=http://127.0.0.1:11434/ -ENV LCG_MODEL=codegeex4 +ENV LCG_MODEL=qwen2.5-coder:1.5b ENV LCG_RESULT_FOLDER=/app/data/results ENV LCG_PROMPT_FOLDER=/app/data/prompts ENV LCG_CONFIG_FOLDER=/app/data/config ENV LCG_SERVER_HOST=0.0.0.0 ENV LCG_SERVER_PORT=8080 -ENV LCG_SERVER_ALLOW_HTTP=true -ENV OLLAMA_HOST=0.0.0.0 -ENV OLLAMA_PORT=11434 +# ENV LCG_SERVER_ALLOW_HTTP=true +# ENV OLLAMA_HOST=127.0.0.1 +# ENV OLLAMA_PORT=11434 # Expose порты -EXPOSE 8080 11434 - -# Переключаемся на пользователя ollama -USER ollama +EXPOSE 8080 WORKDIR /home/ollama diff --git a/Dockerfiles/OllamaServer/Makefile b/Dockerfiles/OllamaServer/Makefile index 8e2b43c..b1f9d86 100644 --- a/Dockerfiles/OllamaServer/Makefile +++ b/Dockerfiles/OllamaServer/Makefile @@ -23,14 +23,27 @@ help: ## Показать справку @echo " make podman-compose-up - Запустить через podman-compose" @echo " make podman-compose-down - Остановить podman-compose" -build: ## Собрать Docker образ +build: ## Собрать Docker образ (требует собранных бинарников в dist/) + @echo "⚠️ Убедитесь, что бинарники собраны: goreleaser build --snapshot --clean" docker build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" -build-podman: ## Собрать Podman образ +build-podman: ## Собрать Podman образ (требует собранных бинарников в dist/) + @echo "⚠️ Убедитесь, что бинарники собраны: goreleaser build --snapshot --clean" podman build -f $(DOCKERFILE) -t $(IMAGE_NAME):$(IMAGE_TAG) $(CONTEXT) @echo "Образ $(IMAGE_NAME):$(IMAGE_TAG) успешно собран" +build-binaries: ## Собрать бинарники перед сборкой образа + @echo "Сборка бинарников..." + cd $(CONTEXT) && goreleaser build --snapshot --clean + @echo "Бинарники собраны в $(CONTEXT)/dist/" + +build-all: build-binaries build ## Собрать бинарники и Docker образ + @echo "✅ Все готово!" + +build-all-podman: build-binaries build-podman ## Собрать бинарники и Podman образ + @echo "✅ Все готово!" + run: ## Запустить контейнер (Docker) docker run -d \ --name $(CONTAINER_NAME) \ diff --git a/Dockerfiles/OllamaServer/QUICKSTART.md b/Dockerfiles/OllamaServer/QUICKSTART.md index bb8faa8..fa1e19f 100644 --- a/Dockerfiles/OllamaServer/QUICKSTART.md +++ b/Dockerfiles/OllamaServer/QUICKSTART.md @@ -4,7 +4,17 @@ 1. Убедитесь, что у вас установлен Docker или Podman 2. Клонируйте репозиторий (если еще не сделали) -3. Перейдите в папку с Dockerfile +3. Соберите бинарники (требуется перед сборкой образа) + +```bash +# Из корня проекта +goreleaser build --snapshot --clean + +# Или используйте скрипт +./deploy/4.build-binaries.sh v2.0.15 +``` + +4. Перейдите в папку с Dockerfile ```bash cd Dockerfiles/OllamaServer @@ -15,14 +25,16 @@ cd Dockerfiles/OllamaServer ### Вариант 1: Docker Compose (рекомендуется) ```bash +# Важно: убедитесь, что бинарники собраны в ../../dist/ docker-compose up -d ``` ### Вариант 2: Ручная сборка и запуск ```bash -# Сборка образа -docker build -f Dockerfile -t lcg-ollama:latest ../.. +# Сборка образа (контекст должен быть корень проекта) +cd ../.. # Переходим в корень проекта +docker build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . # Запуск контейнера docker run -d \ @@ -45,8 +57,9 @@ podman-compose -f podman-compose.yml up -d ### Вариант 2: Ручная сборка и запуск ```bash -# Сборка образа -podman build -f Dockerfile -t lcg-ollama:latest ../.. +# Сборка образа (контекст должен быть корень проекта) +cd ../.. # Переходим в корень проекта +podman build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . # Запуск контейнера podman run -d \ diff --git a/Dockerfiles/OllamaServer/README.md b/Dockerfiles/OllamaServer/README.md index 1652453..a8f0dd1 100644 --- a/Dockerfiles/OllamaServer/README.md +++ b/Dockerfiles/OllamaServer/README.md @@ -7,62 +7,111 @@ ## 📋 Описание Контейнер автоматически запускает: -1. **Ollama сервер** (v0.9.5) на порту 11434 -2. **LCG веб-сервер** на порту 8080 + +1 **Ollama сервер** (v0.9.5) на порту 11434 + +2 **LCG веб-сервер** на порту 8080 Ollama используется как провайдер LLM для генерации Linux команд. ## 🚀 Быстрый старт +### Предварительные требования + +Перед сборкой Docker образа необходимо собрать бинарники: + +```bash +# Из корня проекта +# Используйте goreleaser для сборки бинарников +goreleaser build --snapshot --clean + +# Или используйте скрипт сборки +./deploy/4.build-binaries.sh v2.0.15 +``` + +Убедитесь, что в папке `dist/` есть бинарники: + +- `dist/lcg_linux_amd64_v1/lcg_*` для amd64 +- `dist/lcg_linux_arm64_v8.0/lcg_*` для arm64 + ### Сборка образа #### Docker + ```bash -# Из корня проекта +# Из корня проекта (важно: контекст должен быть корень проекта) docker build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . + +# Или с указанием архитектуры +docker buildx build \ + --platform linux/amd64,linux/arm64 \ + -f Dockerfiles/OllamaServer/Dockerfile \ + -t lcg-ollama:latest . ``` #### Podman + ```bash # Из корня проекта podman build -f Dockerfiles/OllamaServer/Dockerfile -t lcg-ollama:latest . + +# Или с указанием архитектуры +podman build \ + --platform linux/amd64,linux/arm64 \ + -f Dockerfiles/OllamaServer/Dockerfile \ + -t lcg-ollama:latest . ``` ### Запуск контейнера -#### Docker +#### Docker run + ```bash docker run -d \ --name lcg-ollama \ - -p 8080:8080 \ - -p 11434:11434 \ + -p 8080:8080 \ lcg-ollama:latest + ollama serve ``` -#### Podman +#### Podman run + ```bash podman run -d \ --name lcg-ollama \ - -p 8080:8080 \ - -p 11434:11434 \ - lcg-ollama:latest + -p 8989:8080 \ + --restart always \ + lcg-ollama:latest \ + ollama serve ``` +когда контейнер запущен на удаленном хосте - можете воспользоваться консольными возможностями утилиты lcg следующим образом + +``` bash +ssh user@[host_where_contaier_running] 'podman exec -it $(podman ps -q --filter \"ancestor=localhost/lcg-ollama:latest\") lcg [your query] +``` + +``` bash +ssh user@[host_where_contaier_running] 'podman exec -it $(podman ps -q --filter "ancestor=localhost/lcg-ollama:latest") /bin/sh -c "export LCG_MODEL=qwen3:0.6b && lcg config --full"' + ### Использование docker-compose / podman-compose #### Docker Compose + ```bash cd Dockerfiles/OllamaServer docker-compose up -d ``` #### Podman Compose + ```bash cd Dockerfiles/OllamaServer podman-compose -f podman-compose.yml up -d ``` Или используйте встроенную поддержку Podman: + ```bash cd Dockerfiles/OllamaServer podman play kube podman-compose.yml @@ -72,8 +121,8 @@ podman play kube podman-compose.yml После запуска контейнера доступны: -- **LCG веб-интерфейс**: http://localhost:8080 -- **Ollama API**: http://localhost:11434 +- **LCG веб-интерфейс**: +- **Ollama API**: ## ⚙️ Переменные окружения @@ -278,7 +327,8 @@ podman logs -f lcg-ollama ### Просмотр логов -#### Docker +#### Docker log + ```bash # Логи контейнера docker logs lcg-ollama @@ -287,7 +337,8 @@ docker logs lcg-ollama docker logs -f lcg-ollama ``` -#### Podman +#### Podman log + ```bash # Логи контейнера podman logs lcg-ollama @@ -298,24 +349,28 @@ podman logs -f lcg-ollama ### Подключение к контейнеру -#### Docker +#### Docker exec + ```bash docker exec -it lcg-ollama sh ``` -#### Podman +#### Podman exec + ```bash podman exec -it lcg-ollama sh ``` ### Проверка процессов -#### Docker +#### Docker check ps + ```bash docker exec lcg-ollama ps aux ``` -#### Podman +#### Podman check ps + ```bash podman exec lcg-ollama ps aux ``` @@ -325,6 +380,7 @@ podman exec lcg-ollama ps aux ### Рекомендации для продакшена 1. **Используйте аутентификацию**: + ```bash -e LCG_SERVER_REQUIRE_AUTH=true -e LCG_SERVER_PASSWORD=strong_password @@ -339,6 +395,7 @@ podman exec lcg-ollama ps aux - Используйте SSL сертификаты 4. **Ограничьте ресурсы**: + ```bash docker run -d \ --name lcg-ollama \ @@ -390,8 +447,8 @@ docker-compose up -d ## ❓ Поддержка При возникновении проблем: + 1. Проверьте логи: `docker logs lcg-ollama` 2. Проверьте переменные окружения 3. Убедитесь, что порты не заняты 4. Проверьте, что модели загружены в Ollama - diff --git a/Dockerfiles/OllamaServer/STRUCTURE.md b/Dockerfiles/OllamaServer/STRUCTURE.md index 4efc13e..6d95700 100644 --- a/Dockerfiles/OllamaServer/STRUCTURE.md +++ b/Dockerfiles/OllamaServer/STRUCTURE.md @@ -19,14 +19,21 @@ Dockerfiles/OllamaServer/ ## Описание файлов ### Dockerfile -Multi-stage Dockerfile, который: -1. Собирает бинарник LCG из исходного кода -2. Устанавливает Ollama 0.9.5 -3. Создает пользователя ollama -4. Настраивает рабочее окружение + +Dockerfile, который: + +1. Использует готовый образ `ollama/ollama:0.9.5` как базовый +2. Копирует предварительно собранный бинарник LCG из папки `dist/` +3. Выбирает правильный бинарник в зависимости от архитектуры (amd64/arm64) +4. Устанавливает entrypoint.sh для запуска обоих сервисов +5. Настраивает рабочее окружение и переменные окружения + +**Важно**: Перед сборкой образа необходимо собрать бинарники с помощью `goreleaser build --snapshot --clean` ### entrypoint.sh + Скрипт запуска, который: + 1. Запускает Ollama сервер в фоне 2. Ожидает готовности Ollama API 3. Запускает LCG сервер в фоне @@ -34,21 +41,27 @@ Multi-stage Dockerfile, который: 5. Корректно обрабатывает сигналы завершения ### docker-compose.yml / podman-compose.yml + Конфигурация для запуска через compose: + - Настройки портов - Переменные окружения - Volumes для персистентного хранения - Healthcheck ### Makefile + Удобные команды для: + - Сборки образа - Запуска/остановки контейнера - Просмотра логов - Работы с compose ### README.md + Полная документация с: + - Описанием функциональности - Инструкциями по установке - Настройками переменных окружения @@ -56,6 +69,7 @@ Multi-stage Dockerfile, который: - Решением проблем ### QUICKSTART.md + Краткое руководство для быстрого старта. ## Порты @@ -73,6 +87,7 @@ Multi-stage Dockerfile, который: ## Переменные окружения Основные переменные (см. README.md для полного списка): + - `LCG_PROVIDER=ollama` - `LCG_HOST=http://127.0.0.1:11434/` - `LCG_MODEL=codegeex4` @@ -81,31 +96,48 @@ Multi-stage Dockerfile, который: ## Запуск +### Предварительная подготовка + +Перед сборкой образа необходимо собрать бинарники: + +```bash +# Из корня проекта +goreleaser build --snapshot --clean +``` + +Убедитесь, что в папке `dist/` есть бинарники для нужных архитектур. + ### Docker + ```bash cd Dockerfiles/OllamaServer docker-compose up -d ``` ### Podman + ```bash cd Dockerfiles/OllamaServer podman-compose -f podman-compose.yml up -d ``` ### Make + ```bash cd Dockerfiles/OllamaServer -make compose-up -# или +make build-all # Собрать бинарники и Docker образ +make compose-up # Запустить через docker-compose + +# Или для Podman +make build-all-podman make podman-compose-up ``` ## Архитектура Контейнер запускает два сервиса: + 1. **Ollama** (порт 11434) - LLM сервер 2. **LCG** (порт 8080) - Веб-интерфейс и API Оба сервиса работают в одном контейнере и общаются через localhost. - diff --git a/Dockerfiles/OllamaServer/docker-compose.yml b/Dockerfiles/OllamaServer/docker-compose.yml index ca76825..e50790a 100644 --- a/Dockerfiles/OllamaServer/docker-compose.yml +++ b/Dockerfiles/OllamaServer/docker-compose.yml @@ -3,8 +3,9 @@ version: '3.8' services: lcg-ollama: build: - context: ../.. + context: ../.. # Контекст сборки - корень проекта (для доступа к dist/) dockerfile: Dockerfiles/OllamaServer/Dockerfile + # TARGETARCH определяется автоматически Docker на основе платформы хоста container_name: lcg-ollama ports: - "8080:8080" # LCG веб-сервер diff --git a/Dockerfiles/OllamaServer/entrypoint.sh b/Dockerfiles/OllamaServer/entrypoint.sh index f7b6f97..6bd9180 100755 --- a/Dockerfiles/OllamaServer/entrypoint.sh +++ b/Dockerfiles/OllamaServer/entrypoint.sh @@ -32,10 +32,6 @@ cleanup() { kill $LCG_PID 2>/dev/null || true wait $LCG_PID 2>/dev/null || true fi - if [ ! -z "$OLLAMA_PID" ]; then - kill $OLLAMA_PID 2>/dev/null || true - wait $OLLAMA_PID 2>/dev/null || true - fi log "Сервисы остановлены" exit 0 } @@ -48,11 +44,6 @@ if [ ! -f /usr/local/bin/lcg ]; then exit 1 fi -# Проверка наличия Ollama -if [ ! -f /usr/local/bin/ollama ]; then - error "Ollama не найден в /usr/local/bin/ollama" - exit 1 -fi # Создаем необходимые директории mkdir -p "${LCG_RESULT_FOLDER:-/app/data/results}" @@ -60,14 +51,14 @@ mkdir -p "${LCG_PROMPT_FOLDER:-/app/data/prompts}" mkdir -p "${LCG_CONFIG_FOLDER:-/app/data/config}" # Настройка переменных окружения для Ollama -export OLLAMA_HOST="${OLLAMA_HOST:-0.0.0.0}" +export OLLAMA_HOST="${OLLAMA_HOST:-127.0.0.1}" export OLLAMA_PORT="${OLLAMA_PORT:-11434}" export OLLAMA_ORIGINS="*" # Настройка переменных окружения для LCG export LCG_PROVIDER="${LCG_PROVIDER:-ollama}" export LCG_HOST="${LCG_HOST:-http://127.0.0.1:11434/}" -export LCG_MODEL="${LCG_MODEL:-codegeex4}" +export LCG_MODEL="${LCG_MODEL:-qwen2.5-coder:1.5b}" export LCG_RESULT_FOLDER="${LCG_RESULT_FOLDER:-/app/data/results}" export LCG_PROMPT_FOLDER="${LCG_PROMPT_FOLDER:-/app/data/prompts}" export LCG_CONFIG_FOLDER="${LCG_CONFIG_FOLDER:-/app/data/config}" @@ -85,39 +76,7 @@ info "LCG Server: http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" info "Ollama Host: $OLLAMA_HOST:$OLLAMA_PORT" log "==========================================" -# Запускаем Ollama сервер в фоне -log "Запуск Ollama сервера..." -/usr/local/bin/ollama serve & -OLLAMA_PID=$! -# Ждем, пока Ollama запустится -log "Ожидание запуска Ollama сервера..." -sleep 5 - -# Проверяем, что Ollama запущен -if ! kill -0 $OLLAMA_PID 2>/dev/null; then - error "Ollama сервер не запустился" - exit 1 -fi - -# Проверяем доступность Ollama API -max_attempts=30 -attempt=0 -while [ $attempt -lt $max_attempts ]; do - # Проверяем через localhost, так как OLLAMA_HOST может быть 0.0.0.0 - if curl -s -f "http://127.0.0.1:${OLLAMA_PORT}/api/tags" > /dev/null 2>&1; then - log "Ollama сервер готов!" - break - fi - attempt=$((attempt + 1)) - if [ $attempt -eq $max_attempts ]; then - error "Ollama сервер не отвечает после $max_attempts попыток" - exit 1 - fi - sleep 1 -done - -# Запускаем LCG сервер в фоне log "Запуск LCG сервера..." /usr/local/bin/lcg serve \ --host "${LCG_SERVER_HOST}" \ @@ -135,37 +94,6 @@ if ! kill -0 $LCG_PID 2>/dev/null; then fi log "LCG сервер запущен на http://${LCG_SERVER_HOST}:${LCG_SERVER_PORT}" -log "Ollama сервер доступен на http://${OLLAMA_HOST}:${OLLAMA_PORT}" -log "==========================================" -log "Сервисы запущены и готовы к работе!" -log "==========================================" - -# Функция для проверки здоровья процессов -health_check() { - while true; do - # Проверяем Ollama - if ! kill -0 $OLLAMA_PID 2>/dev/null; then - error "Ollama процесс завершился неожиданно" - kill $LCG_PID 2>/dev/null || true - exit 1 - fi - - # Проверяем LCG - if ! kill -0 $LCG_PID 2>/dev/null; then - error "LCG процесс завершился неожиданно" - kill $OLLAMA_PID 2>/dev/null || true - exit 1 - fi - - sleep 10 - done -} - -# Запускаем проверку здоровья в фоне -health_check & -HEALTH_CHECK_PID=$! - -# Ждем завершения процессов -wait $LCG_PID $OLLAMA_PID -kill $HEALTH_CHECK_PID 2>/dev/null || true +# Запускаем переданные аргументы +exec "$@" diff --git a/VERSION.txt b/VERSION.txt index 0e18aae..d640b26 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -v2.0.15 +v.2.0.16 diff --git a/config/config.go b/config/config.go index d2237f3..6d7070f 100644 --- a/config/config.go +++ b/config/config.go @@ -27,6 +27,7 @@ type Config struct { ResultHistory string NoHistoryEnv string AllowExecution bool + Query string MainFlags MainFlags Server ServerConfig Validation ValidationConfig diff --git a/deploy/VERSION.txt b/deploy/VERSION.txt index 0e18aae..d640b26 100644 --- a/deploy/VERSION.txt +++ b/deploy/VERSION.txt @@ -1 +1 @@ -v2.0.15 +v.2.0.16 diff --git a/kustomize/configmap.yaml b/kustomize/configmap.yaml index c3fbbe8..d9fb147 100644 --- a/kustomize/configmap.yaml +++ b/kustomize/configmap.yaml @@ -5,7 +5,7 @@ metadata: namespace: lcg data: # Основные настройки - LCG_VERSION: "v2.0.14" + LCG_VERSION: "v.2.0.16" LCG_BASE_PATH: "/lcg" LCG_SERVER_HOST: "0.0.0.0" LCG_SERVER_PORT: "8080" diff --git a/kustomize/deployment.yaml b/kustomize/deployment.yaml index 480c4ae..94d2f22 100644 --- a/kustomize/deployment.yaml +++ b/kustomize/deployment.yaml @@ -5,7 +5,7 @@ metadata: namespace: lcg labels: app: lcg - version: v2.0.14 + version: v.2.0.16 spec: replicas: 1 selector: @@ -18,7 +18,7 @@ spec: spec: containers: - name: lcg - image: kuznetcovay/lcg:v2.0.14 + image: kuznetcovay/lcg:v.2.0.16 imagePullPolicy: Always ports: - containerPort: 8080 diff --git a/kustomize/kustomization.yaml b/kustomize/kustomization.yaml index 5824368..916f555 100644 --- a/kustomize/kustomization.yaml +++ b/kustomize/kustomization.yaml @@ -15,11 +15,11 @@ resources: # Common labels # commonLabels: # app: lcg -# version: v2.0.14 +# version: v.2.0.16 # managed-by: kustomize # Images # images: # - name: lcg # newName: kuznetcovay/lcg -# newTag: v2.0.14 +# newTag: v.2.0.16 diff --git a/main.go b/main.go index eb86f93..326dee9 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "os/exec" "os/user" "path/filepath" + "slices" "strconv" "strings" "time" @@ -76,6 +77,12 @@ func main() { Usage: config.AppConfig.AppName + " - Генерация Linux команд из описаний", Version: Version, Commands: getCommands(), + Before: func(c *cli.Context) error { + // Применяем флаги приложения к конфигурации перед выполнением любой команды + // Это гарантирует, что флаги будут применены даже для команд, которые не используют основной Action + applyAppFlagsToConfig(c) + return nil + }, UsageText: ` lcg [опции] <описание команды> @@ -144,12 +151,25 @@ lcg [опции] <описание команды> Aliases: []string{"f"}, Usage: "Read part of the command from a file", }, + &cli.StringFlag{ + Name: "model", + Aliases: []string{"M"}, + DefaultText: "Use model from LCG_MODEL or default model", + Usage: "Model to use", + }, &cli.BoolFlag{ Name: "no-history", Aliases: []string{"nh"}, Usage: "Disable writing/updating command history (overrides LCG_NO_HISTORY)", Value: false, }, + &cli.StringFlag{ + Name: "query", + Aliases: []string{"Q"}, + Usage: "Query to send to the model", + DefaultText: "Hello? what day is it today?", + Value: "Hello? what day is it today?", + }, &cli.StringFlag{ Name: "sys", Aliases: []string{"s"}, @@ -181,16 +201,25 @@ lcg [опции] <описание команды> Action: func(c *cli.Context) error { file := c.String("file") system := c.String("sys") + model := c.String("model") + query := c.String("query") // обновляем конфиг на основе флагов - if system != "" { + if c.IsSet("sys") && system != "" { config.AppConfig.Prompt = system } + if c.IsSet("query") && query != "" { + config.AppConfig.Query = query + } if c.IsSet("timeout") { config.AppConfig.Timeout = fmt.Sprintf("%d", c.Int("timeout")) } + if c.IsSet("model") { + config.AppConfig.Model = model + } + promptID := c.Int("prompt-id") timeout := c.Int("timeout") - // сохраняем конкретные значения флагов + config.AppConfig.MainFlags = config.MainFlags{ File: file, NoHistory: c.Bool("no-history"), @@ -203,12 +232,9 @@ lcg [опции] <описание команды> config.AppConfig.MainFlags.Debug = config.AppConfig.MainFlags.Debug || config.GetEnvBool("LCG_DEBUG", false) - // fmt.Println("Debug:", config.AppConfig.MainFlags.Debug) - // fmt.Println("LCG_DEBUG:", config.GetEnvBool("LCG_DEBUG", false)) - args := c.Args().Slice() - if len(args) == 0 { + if len(args) == 0 && config.AppConfig.Query == "" { cli.ShowAppHelp(c) showTips() return nil @@ -231,6 +257,12 @@ lcg [опции] <описание команды> os.Exit(1) } } + + if config.AppConfig.Query != "" { + executeMain(file, system, config.AppConfig.Query, timeout) + return nil + } + executeMain(file, system, strings.Join(args, " "), timeout) return nil }, @@ -251,6 +283,31 @@ lcg [опции] <описание команды> } } +// applyAppFlagsToConfig применяет флаги приложения к конфигурации +// Работает как для основного Action, так и для команд +func applyAppFlagsToConfig(c *cli.Context) { + // Применяем флаг model - проверяем и через IsSet, и значение напрямую + // так как IsSet может не работать для флагов без значения по умолчанию + if model := c.String("model"); model != "" { + config.AppConfig.Model = model + } + + // Применяем флаг sys + if sys := c.String("sys"); sys != "" { + config.AppConfig.Prompt = sys + } + + // Применяем флаг timeout (только если явно установлен) + if c.IsSet("timeout") { + config.AppConfig.Timeout = fmt.Sprintf("%d", c.Int("timeout")) + } + + // Применяем флаг query (игнорируем значение по умолчанию) + if query := c.String("query"); query != "" && query != "Hello? what day is it today?" { + config.AppConfig.Query = query + } +} + func getCommands() []*cli.Command { commands := []*cli.Command{ { @@ -390,6 +447,10 @@ func getCommands() []*cli.Command { }, }, Action: func(c *cli.Context) error { + // Флаги приложения уже применены через глобальный Before hook + // Но применяем их еще раз на случай, если глобальный Before не сработал + applyAppFlagsToConfig(c) + if c.Bool("full") { // Выводим полную конфигурацию в JSON формате showFullConfig() @@ -1027,12 +1088,7 @@ func getServerAllowHTTPForHost(host string) bool { // isSecureHost проверяет, является ли хост безопасным для HTTP func isSecureHost(host string) bool { secureHosts := []string{"localhost", "127.0.0.1", "::1"} - for _, secureHost := range secureHosts { - if host == secureHost { - return true - } - } - return false + return slices.Contains(secureHosts, host) } // showShortConfig показывает краткую конфигурацию