Ollama за обратным прокси-сервером Caddy или Nginx для потоковой передачи HTTPS

HTTPS для Ollama без нарушения потоковой передачи ответов.

Содержимое страницы

Запуск Ollama за обратным прокси-сервером — это самый простой способ обеспечить HTTPS, опциональный контроль доступа и предсказуемое поведение потоковой передачи.

В этой статье рассматривается настройка Caddy и Nginx для доступа к API Ollama, а не код клиентской части.

ollama behind proxy

Если у вас уже есть клиенты на Python или Go, работающие с Ollama, эта статья заполнит пробел: она посвящена входящему трафику и транспорту для того же API.

Чтобы узнать, как Ollama соотносится с vLLM, Docker Model Runner, LocalAI и компромиссами облачного хостинга, см. LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared.

Примеры запросов и код клиента можно найти в Ollama CLI Cheatsheet.

Информацию о пользовательских интерфейсах и слоях для нескольких пользователей см. Open WebUI overview, quickstart and alternatives.

Чтобы понять общую картину самохостинга и контроля данных, см. LLM self-hosting and AI sovereignty.

Для воспроизводимого одноузлевого сервиса Ollama в Docker Compose (постоянные тома, OLLAMA_HOST, видеокарты NVIDIA, обновления) см. Ollama in Docker Compose with GPU and Persistent Model Storage.

Почему стоит проксировать Ollama вместо открытия порта 11434

Ollama спроектирован для локальной работы в первую очередь. По умолчанию он привязывается к localhost на порту 11434, что отлично подходит для рабочей станции разработчика и является негласным намеком на то, что этот порт не предназначен для выхода в интернет.

Я отношусь к порту 11434 как к внутреннему API с высокими затратами. Если он доступен из публичного интернета, любой, кто его найдет, сможет сжечь ваши вычислительные ресурсы CPU или GPU, забить диск загрузкой моделей или просто удерживать соединения открытыми до тайм-аута. Обратный прокси-сервер не делает Ollama безопасным по волшебству, но он предоставляет место для размещения важных средств контроля на границе сети: TLS, аутентификация, тайм-ауты, лимиты частоты запросов и логи.

Это важно, потому что локальный API Ollama не поставляется со встроенным слоем аутентификации. Если вы экспонируете его, вы обычно добавляете аутентификацию на уровне границы сети или держите его приватным, доступным только через доверенную сеть.

Вторая причина касается пользовательского опыта (UX). Ollama по умолчанию потоково передает ответы. Если прокси-сервер буферизирует или сжимает данные в неправильном месте, потоковая передача кажется сломанной, а интерфейсы выглядят так, будто они «думают» без вывода результатов.

Минимальная архитектура и стратегия привязки

Чистая минимальная конфигурация выглядит так:

Клиент (curl, Python, Go, UI)
        |
        | HTTPS (опционально Basic Auth или SSO)
        v
Обратный прокси (Caddy или Nginx)
        |
        | HTTP (частная LAN, localhost или сеть Docker)
        v
Сервер Ollama (ollama serve на 127.0.0.1:11434)

Два практических правила сохраняют эту схему простой и надежной.

Во-первых, держите Ollama в приватной зоне и перенесите экспозицию на прокси. Если Caddy или Nginx работают на том же хосте, проксируйте запросы на 127.0.0.1:11434 и не меняйте адрес привязки Ollama. Если прокси работает на другом хосте (отдельная машина, виртуальная машина или сеть контейнеров), привяжите Ollama к приватному интерфейсу, а не к 0.0.0.0 на публичной сетевой карте, и используйте брандмауэр.

Во-вторых, заранее решите, будут ли браузеры вызывать Ollama напрямую. Если инструмент на базе браузера обращается к Ollama с другого домена, вам, возможно, придется справляться с CORS. Если все обслуживается с одного домена через прокси (рекомендуется для сохранения рассудка), вы часто можете полностью избежать CORS и держать Ollama строгим.

Настройки обратного прокси для потоковой передачи и WebSockets

API Ollama использует обычный HTTP, а его потоковая передача основана на NDJSON (Newline-Delimited JSON). Это означает, что вам нужен прокси, который хорошо справляется с тремя задачами:

  • Не буферизировать потоковые ответы.
  • Не прерывать длительные запросы просто потому, что модель заняла время на генерацию ответа.
  • Если интерфейс использует WebSockets (некоторые используют), корректно передавать запросы Upgrade.

Вы можете сохранить это простым. Во многих случаях «корректная обработка WebSockets» сводится к наличию конфигурации, безопасной для Upgrade, даже если upstream не использует WebSockets сегодня.

Пример Caddyfile для Caddy

Caddy — это вариант «меньше конфигурации, больше настроек по умолчанию». Если вы укажете публичное доменное имя в адресе сайта, Caddy обычно автоматически получает и обновляет сертификаты.

Минимальный обратный прокси, HTTPS и настройки, дружественные к потоковой передаче:

# ollama.example.com A/AAAA -> ваш прокси-хост
ollama.example.com {

    # Опциональная аутентификация Basic Auth на границе.
    # Сгенерируйте хеш пароля с помощью:
    #   caddy hash-password --algorithm bcrypt
    #
    # basic_auth {
    #   alice $2a$12$REDACTED...
    # }

    reverse_proxy 127.0.0.1:11434 {

        # Некоторые настройки предпочитают жестко указывать заголовок Host upstream.
        # Собственная документация Ollama показывает этот паттерн для Nginx.
        header_up Host localhost:11434

        # Для потоковых или чат-подобных рабочих нагрузок предпочтительна низкая задержка.
        # Потоковая передача NDJSON обычно сбрасывает буфер немедленно, но это делает это явным.
        flush_interval -1

        transport http {
            # Избегайте согласования gzip с upstream, если это мешает потоковой передаче.
            compression off

            # Дайте Ollama время загрузить модель и создать первый фрагмент.
            response_header_timeout 10m
            dial_timeout 10s
        }
    }
}

Если у вас уже есть шлюз SSO (oauth2-proxy, Authelia, authentik outpost и т.д.), в Caddy есть директива forward_auth с четкой позицией. Паттерн таков: «сначала аутентификация, затем прокси»:

ollama.example.com {
    forward_auth 127.0.0.1:4180 {
        uri /oauth2/auth
        # Скопируйте заголовки идентификации, которые возвращает ваш шлюз, если они нужны.
        copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
    }

    reverse_proxy 127.0.0.1:11434
}

Пример блока сервера для Nginx

Nginx дает вам больше гибкости. Плюсом является то, что настройки явные, и есть встроенные примитивы для ограничения частоты запросов и ограничения соединений. Минусом является буферизация: Nginx по умолчанию буферизирует проксируемые ответы, что противоположно тому, что вам нужно для потоковой передачи NDJSON.

В этом примере включены:

  • Перенаправление с HTTP на HTTPS
  • Пути к TLS-сертификатам (стиль Certbot)
  • Безопасная для WebSocket передача запросов Upgrade
  • Отключение буферизации прокси для потоковой передачи
  • Более длительные тайм-ауты, чем стандартные 60 секунд
# /etc/nginx/conf.d/ollama.conf

# Обработка заголовка Connection, безопасная для WebSocket
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

# Опциональное ограничение частоты запросов (по IP)
# limit_req_zone $binary_remote_addr zone=ollama_rate:10m rate=10r/s;

server {
    listen 80;
    server_name ollama.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ollama.example.com;

    ssl_certificate     /etc/letsencrypt/live/ollama.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ollama.example.com/privkey.pem;

    # Опциональная аутентификация Basic Auth на границе.
    # auth_basic "Ollama";
    # auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        # Опциональное ограничение частоты
        # limit_req zone=ollama_rate burst=20 nodelay;

        proxy_pass http://127.0.0.1:11434;

        # Совпадение с паттерном документации Ollama при проксировании на localhost.
        proxy_set_header Host localhost:11434;

        # Обработка запросов Upgrade WebSocket (безвредно, если не используется).
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Критично для потоковой передачи NDJSON.
        proxy_buffering off;

        # Предотвращение тайм-аута ожидания токенов (60 сек по умолчанию).
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

Если вам нужен шлюз в стиле SSO в Nginx, эквивалентным паттерном является auth_request. Nginx отправляет подзапрос в ваш сервис аутентификации и проксирует запросы к Ollama только тогда, когда аутентификация возвращает статус 2xx.

Особенности автоматизации TLS и обновления сертификатов

Что касается TLS, разделение операционных задач простое.

С Caddy TLS обычно является «частью обратного прокси». Автоматический HTTPS — одна из его флагманских функций, поэтому выпуск и обновление сертификатов связаны с запуском Caddy, работоспособностью DNS и открытием портов 80 и 443.

С Nginx TLS обычно представляет собой «отдельный клиент ACME плюс Nginx». Распространенный режим отказа — не криптография, а инфраструктура:

  • Порт 80 недоступен для вызовов HTTP-01.
  • Сертификаты хранятся в контейнере, но не сохраняются при перезапуске.
  • Лимиты частоты при повторных новых установках или тестовых развертываниях.

Нюанс, который имеет значение для долгосрочных сервисов, заключается в том, что срок действия сертификатов по дизайну короткий. Относитесь к обновлениям как к требованию фоновой автоматизации, а не как к ежегодному событию в календаре.

Аутентификация, контроль злоупотреблений и проверка

Это та часть, которая делает публичный конечный пункт LLM профессиональным.

Варианты аутентификации, от простых до элегантных

Аутентификация Basic Auth на уровне прокси проста, но удивительно эффективна для приватного конечного пункта. Она также легко применяется как к HTTP-запросам, так и к обновлениям WebSocket.

Если вам нужны потоки входа в систему, удобные для браузера, паттерны forward_auth и auth_request являются общепринятыми. Ваш прокси остается без состояния, а шлюз аутентификации управляет сессиями и MFA. Компромиссом является большее количество движущихся частей.

Если вы уже используете Open WebUI, вы также можете полагаться на его аутентификацию на уровне приложения и держать сам Ollama приватным. В этом случае прокси защищает Open WebUI, а не Ollama напрямую.

Если вам вообще не нужен публичный доступ, подход только через сеть может быть чище. Например, Tailscale Serve может экспонировать локальный сервис внутри вашей сети tailnet без открытия входящих портов на вашем роутере.

Основы защиты от злоупотреблений для дорогостоящего API

Ollama — это мощный локальный API, и его поверхность выходит за рамки генерации. У него есть конечные точки для чата, эмбеддингов, списка моделей и проверки версии. Относитесь ко всему API как к чувствительному.

Официальная справка по API (конечные точки и потоковая передача): https://docs.ollama.com/api

На уровне прокси есть три простых контроля, которые уменьшают боль первого дня:

  • Ограничение частоты запросов по IP на конечных точках генерации.
  • Лимиты соединений, чтобы остановить небольшое количество клиентов, удерживающих всё открытым.
  • Консервативные тайм-ауты, соответствующие вашей модели и аппаратным возможностям, а не общим веб-стандартам.

На уровне Ollama также можно отклонять перегрузку с помощью статуса 503, и есть серверные настройки для очередей. Ограничение частоты запросов прокси-сервера помогает реже доходить до этого.

Чек-лист проверки

Используйте те же проверки, что и для любого потокового API.

  1. Базовая связность и TLS

    • curl -sS https://ollama.example.com/api/version
    • curl -sS https://ollama.example.com/api/tags | head
  2. Потоковая передача работает от начала до конца (без буферизации)

    • curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'

    Если вы используете Basic Auth:

    • curl -N -u alice:REDACTED https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'
  3. Проверка интерфейса в браузере

    • Загрузите свой чат-интерфейс и запустите ответ.
    • Если интерфейс использует WebSockets, убедитесь, что вы не видите ошибок 400 или 426, и соединение остается открытым во время генерации.

Если вывод curl появляется только в конце, это почти всегда буферизация на прокси-сервере. Перепроверьте настройку proxy_buffering off в Nginx и рассмотрите принудительную сброску с низкой задержкой в Caddy для блока сайта Ollama.