Caddy 또는 Nginx 역 프록시를 통한 HTTPS 스트리밍을 지원한 Ollama

스트리밍 응답을 깨지 않고 HTTPS에서 Ollama 사용

Page content

Ollama 를 역 프록시 뒤에 두는 것이 HTTPS, 선택적 접근 제어, 예측 가능한 스트리밍 동작을 얻는 가장 간단한 방법입니다.

이 글은 클라이언트 코드에 대한 것이 아니라 Ollama API 를 위한 Caddy 와 Nginx 의 Ingress 에 초점을 맞춥니다.

ollama behind proxy

이미 Ollama 와 통신하는 Python 또는 Go 클라이언트를 보유하고 있다면, 이 글은 동일한 API 를 위한 Ingress 와 전송 계층을 채우는 핵심 요소입니다.

Ollama 가 vLLM, Docker Model Runner, LocalAI 및 클라우드 호스팅의 절충안과 어떻게 조화를 이루는지 확인하려면 다음을 참조하세요. 2026 년 LLM 호스팅: 로컬, 자체 호스팅 및 클라우드 인프라 비교.

요청 예제와 클라이언트 코드는 다음을 참조하세요. Ollama CLI 치트시트.

UI 및 다중 사용자 계층에 대해서는 다음을 참조하세요. Open WebUI 개요, 빠른 시작 및 대안.

자체 호스팅과 데이터 제어에 대한 큰 그림은 다음을 참조하세요. LLM 자체 호스팅과 AI 주권.

Docker Compose 를 통한 재현 가능한 단일 노드 Ollama 서비스 (지속 가능한 볼륨, OLLAMA_HOST, NVIDIA GPU, 업그레이드) 에 대해서는 다음을 참조하세요. GPU 와 지속 가능한 모델 저장을 위한 Docker Compose 에서의 Ollama.

포트 11434 를 노출하는 대신 Ollama 를 프록시해야 하는 이유

Ollama 는 기본적으로 로컬에서 실행되도록 설계되었습니다. 기본 설정에서 포트 11434 에 로컬호스트로 바인딩되므로 개발자 워크스테이션에는 훌륭하지만, 이 원시 포트가 인터넷에 직접 노출되어서는 안 된다는 은근한 힌트이기도 합니다.

저는 포트 11434 를 내부적이고 고비용의 API 로 취급합니다. 만약 이 포트가 공개 인터넷에 접근 가능하다면, 이를 발견한 누구나 CPU 나 GPU 시간을 소진시키거나, 모델을 다운로드하여 디스크를 채우거나, 타임아웃이 발생할 때까지 연결을 열어둘 수 있습니다. 역 프록시가 Ollama 를 마법처럼 더 안전하게 만들지는 않지만, 가장 중요한 제어 장치인 TLS, 인증, 타임아웃, 속도 제한, 로그를 엣지에 배치할 수 있는 장소를 제공합니다.

이는 로컬 Ollama API 에는 기본 인증 계층이 없기 때문에 중요합니다. 이를 노출하는 경우 일반적으로 엣지에서 인증을 추가하거나 신뢰할 수 있는 네트워크에서만 접근 가능하도록 비공개로 유지해야 합니다.

두 번째 이유는 사용자 경험 (UX) 입니다. Ollama 는 기본적으로 응답을 스트리밍합니다. 프록시가 잘못된 위치에서 버퍼링하거나 압축하면 스트리밍이 끊긴 것처럼 느껴지고 UI 는 출력이 없이 “생각 중"인 것처럼 보입니다.

최소 아키텍처와 바인딩 전략

깔끔한 최소 아키텍처는 다음과 같습니다.

Client (curl, Python, Go, UI)
        |
        | HTTPS (선택적 Basic Auth 또는 SSO)
        v
Reverse proxy (Caddy 또는 Nginx)
        |
        | HTTP (비공개 LAN, localhost 또는 Docker 네트워크)
        v
Ollama 서버 (127.0.0.1:11434 에서 ollama serve)

두 가지 실용적인 규칙이 이 구조를 가장 좋은 방식으로 단순하게 유지합니다.

첫째, Ollama 를 비공개로 유지하고 노출을 프록시 쪽으로 옮깁니다. Caddy 나 Nginx 가 같은 호스트에서 실행된다면 127.0.0.1:11434 로 프록시하고 Ollama 의 바인딩 주소를 변경하지 마세요. 프록시가 다른 곳에서 실행되는 경우 (별도의 호스트, 별도의 VM, 또는 컨테이너 네트워크) Ollama 를 공개 NIC 의 0.0.0.0 이 아닌 비공개 인터페이스에 바인딩하고 방화벽에 의존하세요.

둘째, 브라우저가 Ollama 를 직접 호출할지 여부를 조기에 결정하세요. 브라우저 기반 도구가 다른 출처에서 Ollama 를 호출한다면 CORS 문제를 처리해야 할 수 있습니다. 모든 것이 프록시를 통해 하나의 도메인에서 제공된다면 ( Sanity 를 위해 권장), 일반적으로 CORS 를 완전히 피하고 Ollama 를 엄격하게 유지할 수 있습니다.

스트리밍과 WebSockets 을 위한 역 프록시 설정

Ollama 의 API 는 일반적인 HTTP 이며, 스트리밍은 줄바꿈으로 구분된 JSON(NDJSON) 을 사용합니다. 즉, 다음 세 가지를 잘 수행할 수 있는 프록시가 필요합니다.

  • 스트리밍 응답을 버퍼링하지 않아야 합니다.
  • 모델이 응답에 시간이 걸린다고 해서 장시간 요청을 종료하지 않아야 합니다.
  • UI 가 WebSockets 를 사용한다면 (일부 UI 는 사용합니다), Upgrade 헤더를 깔끔하게 전달해야 합니다.

이를 간단하게 유지할 수 있습니다. 많은 경우 “올바른 WebSockets 처리"는 업스트림이 현재 WebSockets 를 사용하지 않더라도 Upgrade 에 안전한 설정을 갖는 것만으로도 충분합니다.

Caddy Caddyfile 예제

Caddy 는 “설정보다 기본값이 많다"는 옵션입니다. 사이트 주소에 공개 도메인 이름을 넣으면 Caddy 는 일반적으로 자동으로 인증서를 발급하고 갱신합니다.

최소한의 역 프록시, HTTPS, 스트리밍 친화적인 설정:

# ollama.example.com A/AAAA -> your proxy host
ollama.example.com {

    # 엣지에서의 선택적 Basic Auth.
    # 비밀번호 해시를 생성하려면 다음을 실행하세요:
    #   caddy hash-password --algorithm bcrypt
    #
    # basic_auth {
    #   alice $2a$12$REDACTED...
    # }

    reverse_proxy 127.0.0.1:11434 {

        # 일부 설정은 업스트림 Host 헤더를 고정하는 것을 선호합니다.
        # Ollama 의 공식 문서에서도 Nginx 를 위한 이 패턴을 보여줍니다.
        header_up Host localhost:11434

        # 스트리밍이나 채팅과 같은 워크로드에는 낮은 지연 시간이 중요합니다.
        # NDJSON 스트리밍은 일반적으로 즉시 플러시되지만, 이를 명시적으로 설정합니다.
        flush_interval -1

        transport http {
            # 스트리밍에 방해가 되는 경우 업스트림 gzip 협상을 방지합니다.
            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
        # 필요시 게이트웨이에서 반환된 ID 헤더를 복사합니다.
        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 전달
  • 스트리밍 친화적인 proxy_buffering off
  • 기본값인 60 초보다 긴 타임아웃
# /etc/nginx/conf.d/ollama.conf

# WebSocket 안전한 Connection 헤더 처리
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 문서 패턴에 맞춰 설정합니다.
        proxy_set_header Host localhost:11434;

        # WebSocket Upgrade 처리 (사용하지 않아도 해가 없음).
        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;
    }
}

Nginx 에서 SSO 스타일의 게이트를 원한다면, 이에 해당하는 패턴은 auth_request 입니다. Nginx 는 인증 서비스에 하위 요청을 보내고, 인증이 2xx 를 반환할 때만 Ollama 로 프록시합니다.

TLS 자동화 및 갱신 주의사항

TLS 에 관해 운영 측면의 구분은 간단합니다.

Caddy 의 경우 TLS 는 일반적으로 “역 프록시 일부"입니다. 자동 HTTPS 는 Caddy 의 대표 기능 중 하나이므로 인증서 발급 및 갱신은 Caddy 를 실행하고 DNS 가 작동하며 포트 80 과 443 을 노출하는 것과 결합됩니다.

Nginx 의 경우 TLS 는 일반적으로 “별도의 ACME 클라이언트와 Nginx"입니다. 일반적인 실패 모드는 암호학 문제가 아니라 배관 문제입니다:

  • HTTP-01 챌린지를 위한 포트 80 이 도달 가능하지 않음.
  • 인증서가 컨테이너에 저장되지만 지속되지 않음.
  • 반복적인 새 설치 또는 테스트 배포 시 속도 제한.

장기간 서비스에서 중요한 미묘한 점은 인증서 수명이 설계상 짧다는 것입니다. 갱신을 연례 캘린더 이벤트가 아닌 백그라운드 자동화 요구사항으로 취급하세요.

인증, 악용 방지 및 검증

이 부분이 인터넷에 노출된 LLM 엔드포인트를 전문적으로 느끼게 합니다.

인증 옵션: 단순한 것부터 우아한 것까지

프록시에서의 Basic Auth 는 단순하지만, 비공개 엔드포인트에서는 놀라울 정도로 효과적입니다. 또한 HTTP 요청과 WebSocket 업그레이드 모두에 쉽게 적용할 수 있습니다.

브라우저 친화적인 로그인 흐름을 원한다면 forward auth 와 auth_request 가 일반적인 패턴입니다. 프록시는 상태를 유지하지 않고, 인증 게이트웨이가 세션과 MFA 를 관리합니다. 단점은 이동해야 할 부분이 더 많아진다는 것입니다.

이미 Open WebUI 를 실행 중이라면 애플리케이션 수준의 인증에 의존하고 Ollama 자체는 비공개로 유지할 수 있습니다. 이때 프록시는 Ollama 가 아닌 Open WebUI 를 보호하게 됩니다.

공개 접근이 전혀 필요하지 않다면 네트워크 전용 접근 방식이 더 깔끔할 수 있습니다. 예를 들어 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. 브라우저 UI 정상성 확인

    • 채팅 UI 를 로드하고 응답을 트리거하세요.
    • UI 가 WebSockets 를 사용한다면, 400 또는 426 오류가 보이지 않고 생성 중 연결이 유지되는지 확인하세요.

만약 curl 출력 결과가 끝에서만 나타나면 거의 항상 프록시에서의 버퍼링 문제입니다. Nginx 에서 proxy_buffering off 를 다시 확인하고, Caddy 의 Ollama 사이트 블록에서 저지연 플러시를 강제하는 것을 고려하세요.