Post

(폐쇄망 LLM 7-4) Open-WebUI 설치 - 로컬 ChatGPT 인터페이스 구축

폐쇄망/내부망에서 Open-WebUI로 ChatGPT와 유사한 웹 인터페이스를 구축하는 방법. Docker 이미지를 오프라인 환경으로 전송하고 vLLM 서버와 연동합니다.

(폐쇄망 LLM 7-4) Open-WebUI 설치 - 로컬 ChatGPT 인터페이스 구축

이전 글: vLLM 서버 구축

이 글은 망분리 환경 AI 배포 시리즈의 열 번째 글입니다.

다음 글: Mistral-Vibe 설치

이번 글의 목표

vLLM 서버를 구축했습니다. 이제 사용자들이 실제로 AI와 대화할 수 있는 웹 인터페이스를 설치해 볼까요?

Open-WebUI는 ChatGPT와 유사한 UI를 제공하는 오픈소스 프로젝트입니다. vLLM의 OpenAI 호환 API와 연동하면 폐쇄망에서도 ChatGPT와 동일한 사용 경험을 제공할 수 있죠.

설치 흐름은 vLLM과 동일합니다. Docker 이미지를 pull → save → 전송 → load 순서로 진행하면 됩니다.


1. Open-WebUI Docker 이미지 설치

vLLM과 동일한 방식으로 Docker 이미지를 옮기면 됩니다.

1
2
3
4
# 인터넷망
docker pull ghcr.io/open-webui/open-webui:main
docker save -o open-webui.tar ghcr.io/open-webui/open-webui:main
gzip open-webui.tar

압축 파일을 폐쇄망으로 옮긴 후:

1
2
3
4
# 폐쇄망
gunzip open-webui.tar.gz
docker load -i open-webui.tar
docker images | grep open-webui

2. 임베딩 모델 다운로드

Open-WebUI는 RAG(Retrieval-Augmented Generation) 기능을 위해 임베딩 모델을 사용합니다.

임베딩 모델은 텍스트를 고차원 벡터로 변환하는 역할을 합니다. Open-WebUI에서 문서를 업로드하면 임베딩 모델이 문서 내용을 벡터로 변환해서 저장하죠. 이후 사용자가 질문하면 질문도 벡터로 변환하고, 저장된 문서 벡터들과 비교해서 가장 유사한 내용을 찾아냅니다. 이렇게 찾은 관련 문서를 LLM에 컨텍스트로 전달해서 더 정확한 답변을 생성합니다.

임베딩 모델이 없으면? 파일 업로드는 가능하지만 업로드한 파일 내용을 분석할 수 없습니다. 임베딩이 없으면 유사도 검색 자체가 불가능하거든요. RAG 기능을 사용하려면 임베딩 모델이 필수입니다.

온라인 환경에서는 자동으로 다운로드하지만, 저희는 망분리 환경이니까 인터넷 망에서 다운로드 받은 후 폐쇄망으로 옮겨야 합니다. 임베딩 엔진은 로컬 SentenceTransformer, Ollama, OpenAI 호환 API, Azure OpenAI를 지원합니다. 저는 무난하게 sentence-transformers의 all-MiniLM-L6-v2 모델을 사용해 보겠습니다.

1
2
3
4
# 인터넷망
hf download \
  sentence-transformers/all-MiniLM-L6-v2 \
  --local-dir ./all-MiniLM-L6-v2

다운로드한 all-MiniLM-L6-v2 폴더를 폐쇄망의 ~/local-models 디렉토리로 옮기면 됩니다.

3. Open-WebUI 서버 실행

자, 이제 오프라인 모드로 Open-WebUI를 실행해 봅시다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash

DATA_DIR="${HOME}/Projects/local-ai/open-webui-data"
MODELS_DIR="${HOME}/local-models"

docker rm -f open-webui 2>/dev/null || true

docker run -d --rm \
    --name open-webui \
    --add-host=host.docker.internal:host-gateway \
    -v "${DATA_DIR}:/app/backend/data" \
    -v "${MODELS_DIR}/all-MiniLM-L6-v2:/models/all-MiniLM-L6-v2:ro" \
    -p 3000:8080 \
    -e OFFLINE_MODE=true \
    -e RAG_EMBEDDING_MODEL="/models/all-MiniLM-L6-v2" \
    -e RAG_EMBEDDING_MODEL_AUTO_UPDATE=false \
    -e ENABLE_OLLAMA_API=false \
    -e OPENAI_API_BASE_URL="http://host.docker.internal:8080/v1" \
    -e OPENAI_API_KEY="not-needed" \
    -e ENABLE_RAG_WEB_SEARCH=false \
    -e ENABLE_OAUTH_SIGNUP=false \
    -e ENABLE_IMAGE_GENERATION=false \
    -e ENABLE_COMMUNITY_SHARING=false \
    -e SCARF_NO_ANALYTICS=true \
    -e ANONYMIZED_TELEMETRY=false \
    -e DO_NOT_TRACK=true \
    ghcr.io/open-webui/open-webui:main

echo "Open WebUI starting on http://{Localhost IP address}:3000"

아래는 옵션에 대한 설명입니다.

Docker 옵션

  • -d --rm: 백그라운드 실행, 종료 시 컨테이너 자동 삭제
  • --name open-webui: 컨테이너 이름 지정
  • --add-host=host.docker.internal:host-gateway: 컨테이너에서 호스트의 서비스(vLLM)에 접근할 수 있도록 설정
  • -p 3000:8080: 호스트 3000번 포트를 컨테이너 8080번 포트에 매핑

볼륨 마운트 (-v)

  • ${DATA_DIR}:/app/backend/data: 사용자 정보, 채팅 기록, 설정 등 Open-WebUI 데이터 영속화
  • ${MODELS_DIR}/all-MiniLM-L6-v2:/models/all-MiniLM-L6-v2:ro: 임베딩 모델 마운트 (읽기 전용)

환경 변수 (-e)

오프라인 모드 설정

  • OFFLINE_MODE=true: 완전 오프라인 모드 활성화. HuggingFace 다운로드 시도 및 버전 체크 비활성화
  • RAG_EMBEDDING_MODEL="/models/all-MiniLM-L6-v2": 로컬 임베딩 모델 경로 지정
  • RAG_EMBEDDING_MODEL_AUTO_UPDATE=false: 임베딩 모델 자동 업데이트 비활성화

LLM 연결 설정

  • ENABLE_OLLAMA_API=false: Ollama API 비활성화. OpenAI 호환 API만 사용
  • OPENAI_API_BASE_URL="http://host.docker.internal:8080/v1": vLLM 서버 주소
  • OPENAI_API_KEY="not-needed": API 키 플레이스홀더. 로컬 서버에서는 검증하지 않지만 필수 값

기능 비활성화

  • ENABLE_RAG_WEB_SEARCH=false: 웹 검색 RAG 비활성화 (인터넷 필요)
  • ENABLE_OAUTH_SIGNUP=false: OAuth 가입 비활성화 (외부 인증 제공자 불가)
  • ENABLE_IMAGE_GENERATION=false: 이미지 생성 기능 비활성화
  • ENABLE_COMMUNITY_SHARING=false: 커뮤니티 공유 비활성화 (인터넷 필요)

텔레메트리 비활성화

  • SCARF_NO_ANALYTICS=true: Scarf 분석 비활성화
  • ANONYMIZED_TELEMETRY=false: 익명 텔레메트리 비활성화
  • DO_NOT_TRACK=true: 추적 방지 플래그

4. 접속 확인

브라우저에서 http://localhost:3000에 접속해 보세요. 다음 화면이 나오면 성공입니다:

Open-WebUI 시작 화면 Open-WebUI 시작 화면

5. 관리자 계정 생성

“시작하기” 버튼을 클릭하면 관리자 계정 생성 화면이 나옵니다:

관리자 계정 생성 관리자 계정 생성 화면

이름, 이메일, 비밀번호를 입력하고 “관리자 계정 생성” 버튼을 클릭하세요. 처음 생성하는 계정이 자동으로 관리자 권한을 갖게 됩니다.

6. 테스트

관리자 계정으로 로그인하면 채팅 화면이 나옵니다. vLLM에서 서빙 중인 모델을 선택하고 메시지를 보내보세요:

채팅 테스트 Open-WebUI 채팅 화면

응답이 잘 나옵니다. vLLM과 Open-WebUI 연동이 완료됐습니다.

7. 사용자 관리

관리자 패널에서 사용자를 직접 추가할 수 있습니다. 좌측 하단의 프로필 아이콘 → “관리자 패널”로 진입하면 됩니다 사용자가 추가되면 해당 사용자는 별도의 설치 없이 http://{서버IP}:3000에 접속해서 바로 사용할 수 있습니다. 웹 브라우저만 있으면 됩니다.

주의: 관리자 패널 → 설정 → 모델에서 모델을 공개로 설정해야 다른 사용자들에게 모델이 표시됩니다. 이 설정을 안 하면 관리자만 모델을 사용할 수 있어요.

주의: 컨테이너 종료 시 반드시 docker stop open-webui 명령어로 정상 종료하세요. kill 등으로 강제 종료하면 data 폴더가 오염되어 재시작 시 임베딩이 작동하지 않을 수 있습니다. 이 경우 데이터 폴더를 초기화해야 하는데, 그러면 사용자 정보와 채팅 기록이 모두 삭제됩니다.


다음 글

vLLM 서버와 Open-WebUI 설치가 완료되었습니다. 이제 에이전틱 코딩을 해볼 차례입니다.

에이전틱 코딩 도구는 모델에 따라 선택해야 합니다:

  • Qwen 계열: tool calling이 XML 형식이라 Qwen-Code가 아니면 호환이 어렵습니다
  • Mistral 계열: system/user 메시지 처리 방식 때문에 Mistral-Vibe가 아니면 완벽한 호환이 어렵습니다
  • 그 외: 대부분 Claude Code + claude-code-router로 사용 가능합니다

Claude Code는 이전 글에서 다뤘으니, 다음 글에서는 Mistral-VibeQwen-Code를 설치해봅니다.


시리즈 목차

전체 목차는 AI 활용에서 확인하실 수 있습니다.

This post is licensed under CC BY 4.0 by the author.