폐쇄망 설치와 업데이트
원천 · framework/evomind/cli/evo기준 · 릴리스 0.23.1커밋 · 7e210096파일 · docs/closed-network.md기준선 · 2026-11-12
외부 인터넷이 차단된 기관(공공망 등)에서 evo를 설치하고 업데이트하는 방법이다. 대상 독자는 기관의 시스템 운영자와 릴리스 담당자이다.
이 문서의 주소(
nexus.example.internal등)는 자리표시자이다. 실제 기관 주소를 이 문서나 저장소에 적지 않는다. 기관용 빌드와evo --version의 기관 식별자 표시는 의 기능이다. 해당 변경이 반영된 릴리스부터 유효하다.
1. 전체 그림
섹션 제목: “1. 전체 그림”- 모델은 망 안의 내부 서버(vLLM, Ollama, 내부 게이트웨이 등)를 쓴다. 모델 연결 설정은
docs/cli.md의/provider와 모델 표(base_url)를 본다. - 업데이트 파일은 기관의 내부 Nexus에 올려 두고 evo가 거기서 받는다. 기관용 바이너리에는 그 기관의 Nexus 주소가 빌드 시점에 들어 있어 사용자가 환경변수를 따로 설정하지 않아도 된다.
- 키 파일로 업데이트 주소 받기 : 조직 키 파일에
"update": {"url": "<기관 Nexus 주소>"}를 넣어 서명해 배포하면, 일반 바이너리도 그 기관 Nexus에서evo update를 한다. 이때는 기관용 빌드가 필요 없다. 키 파일 형식은docs/org-keyfile.md를 본다. 아래 기관용 빌드는 키 파일 없이 쓰는 기관을 위해 남겨 둔다. - 회사 GitLab·회사 Nexus에는 접속하지 않는다. 업데이트 조회와 다운로드는 내부 Nexus만 쓴다(GitLab은 토큰을 설정했을 때만 폴백 대상이며 폐쇄망에서는 필요 없다).
- 버전 번호는 일반 릴리스와 같다. 기관은 필요한 버전만 받을 수 있다(예: 11과 13만 받고 12는 건너뜀).
2. 기관용 산출물 받기
섹션 제목: “2. 기관용 산출물 받기”릴리스 담당자가 이미 만들어진 보호 태그의 파이프라인에서 release:institution job을 수동 실행한다 (docs/cli.md의 “기관용 빌드 만들기”).
- 입력: 기관 식별자, 그 기관의 내부 Nexus 주소, 대상 OS(기본
linux/amd64) - 결과(CI artifact):
dist/<기관>/evo_<태그>_<os>_<arch>(Windows는.exe)와dist/<기관>/sha256sums.txt
이 파일들을 반출 승인 절차에 따라 폐쇄망으로 반입한다.
3. 반입 설치 (처음 설치)
섹션 제목: “3. 반입 설치 (처음 설치)”Linux 예시. 다른 OS도 같은 순서이다(Windows는 evo_<태그>_windows_<arch>.exe).
- 반입한 바이너리와
sha256sums.txt를 같은 폴더에 둔다. - 해시를 확인한다.
sha256sum -c sha256sums.txt
OK가 아니면 설치하지 않는다. - 실행 권한을 주고 PATH에 있는 폴더(예:
~/.local/bin)에evo라는 이름으로 둔다.chmod 0755 evo_<태그>_linux_amd64cp evo_<태그>_linux_amd64 ~/.local/bin/evo - 버전과 기관 식별자를 확인한다.
다른 기관의 식별자가 보이면 잘못된 바이너리이다. 설치하지 말고 교체한다.evo --versionevo version <태그> (commit …, …, institution <기관>)
- 모델 연결을 설정한다(내부
base_url):docs/cli.md.
4. 내부 Nexus 구성
섹션 제목: “4. 내부 Nexus 구성”evo는 다음을 기대한다 (internal/update의 NexusRepoName, NexusRepoPath, assetURLs, 조회 코드).
| 항목 | 값 |
|---|---|
| 저장소 | raw(hosted) 저장소 이름 evo-bin |
| 파일 경로 | repository/evo-bin/<태그>/evo_<태그>_<os>_<arch>[.exe] (회사 Nexus는 evo-bin/evo-cli/release/<태그>/를 먼저 쓰지만, 기관 Nexus는 지금처럼 루트에 두면 된다. evo가 새 위치에 없으면 루트에서 받는다) |
| 매니페스트 | 같은 폴더의 sha256sums.txt (줄 형식 해시 파일이름) |
| 읽기 권한 | 익명 읽기 (evo는 토큰을 보내지 않는다) |
| 최신 버전 | repository/evo-bin/install/latest (내용 = 태그 한 줄, 예: 0.22.0). 있으면 이것을 최신으로 본다 |
| 조회 API | install/latest가 없을 때 Nexus REST 검색 GET /service/rest/v1/search/assets?repository=evo-bin&limit=1000 을 익명으로 호출할 수 있어야 한다 |
주의:
- 파일 이름은 표준 이름이어야 한다. evo는
evo_<태그>_<os>_<arch>를 정확히 이름으로 찾고 매니페스트도 그 이름으로 검증한다. 이름을 바꾸면 업데이트가 404로 실패한다. 기관 식별자는 파일 이름이 아니라 CI 산출물의 폴더(dist/<기관>/)로 구분한다. - 매니페스트에는 그 태그 폴더에 올린 모든 바이너리의 줄이 있어야 한다. 각 사용자는 자기 OS·아키텍처 이름의 줄로 검증한다.
- 최신 버전은
install/latest가 있으면 그 값, 없으면 이 저장소에 올라간 가장 높은X.Y.Z폴더이다.install/latest를 두면 새 버전 파일을 모두 올린 뒤에 그 값을 바꾼다(먼저 바꾸면 받기가 실패한다). 두지 않으면 폴더 검색으로 찾는다. 버전은 숫자 3개 형식만 인정되므로 폴더 이름에 접미사를 붙이지 않는다. 최신 조회는 기관 자신의 Nexus만 보므로 중간 버전이 없어도 된다.
올리는 방법(예):
curl -fsS -X PUT -u "<사용자>:<비밀번호>" --data-binary @evo_<태그>_linux_amd64 \ "https://nexus.example.internal/repository/evo-bin/<태그>/evo_<태그>_linux_amd64"curl -fsS -X PUT -u "<사용자>:<비밀번호>" --data-binary @sha256sums.txt \ "https://nexus.example.internal/repository/evo-bin/<태그>/sha256sums.txt"설치기가 함께 설치하는 도구
섹션 제목: “설치기가 함께 설치하는 도구”한 줄 설치기는 Node.js(없거나 최신 LTS보다 낮은 주 버전)·glab(없거나 최신보다 낮음)·Windows git(MinGit, 없을 때)을 같은 저장소의 deps/에서 받아 설치한다. 폐쇄망 Nexus에도 같은 구조로 올려 두면 기관 사용자도 자동으로 받는다. 파일이 없으면 경고만 하고 evo 설치는 계속된다. Linux·macOS의 git은 OS 패키지 관리자·Homebrew·Xcode 도구로 설치하므로, 폐쇄망 기관은 기관의 패키지 저장소(apt·yum 프록시 등)가 그 역할을 한다.
경로 (repository/evo-bin/ 아래) |
내용 |
|---|---|
deps/node/latest-lts |
설치할 Node.js 버전 한 줄 (예: 24.22.0) |
deps/node/v<버전>/ |
nodejs.org 원본 파일 그대로: node-v<버전>-{linux-x64,linux-arm64,darwin-x64,darwin-arm64}.tar.gz, node-v<버전>-win-{x64,arm64}.zip, SHASUMS256.txt |
deps/glab/latest |
glab 버전 한 줄 (예: 1.123.0) |
deps/glab/<버전>/ |
gitlab.com 원본 그대로: glab_<버전>_{linux,darwin}_{amd64,arm64}.tar.gz, glab_<버전>_windows_{amd64,arm64}.zip, checksums.txt |
deps/git/latest |
MinGit 버전 한 줄 (예: 2.56.0.2, Windows 전용) |
deps/git/<버전>/ |
MinGit-<버전>-64-bit.zip, MinGit-<버전>-arm64.zip, sha256sums.txt |
- 채우는 방법: 인터넷이 되는 PC에서
install/mirror-deps.py를 실행한다. nodejs.org의 최신 LTS, glab 최신, Git for Windows 최신 MinGit을 받아 원본 체크섬으로 확인한 뒤에만 올리고, 모든 파일을 올린 뒤latest파일을 바꾼다. 이미 같은 버전이면 건너뛴다.- 바로 올리기:
NEXUS_URL=https://nexus.example.internal NEXUS_USER=… NEXUS_PASSWORD=… python3 install/mirror-deps.py - 반입용으로 디스크에 모으기:
DRY_RUN=1 MIRROR_OUT=./deps-out python3 install/mirror-deps.py→deps-out/deps/…를 그대로 반입해 같은 경로로 올린다.
- 바로 올리기:
- 회사 Nexus는 CI의 수동 job
mirror_deps(main 브랜치)로 갱신한다. 새 LTS가 나오면 이 job을 한 번 실행하면 그 뒤 설치부터 반영된다. - 라이선스: Node.js·glab은 MIT, Git(MinGit)은 GPLv2이다. 기관 내부 재배포 조건은 각 기관 정책을 따른다.
5. 업데이트
섹션 제목: “5. 업데이트”evo update --check: 내부 Nexus에서 최신 버전을 조회한다. 최신이면 종료 코드 0, 새 버전이 있으면 10.evo update: 다운로드 → sha256 검증 → 실행 확인 → 전환 순서이다. 중간에 실패하면 기존 설치는 그대로 남는다. 최근 3개 버전을 보관해 되돌릴 수 있다.- 대화형 화면은 시작할 때 하루 한 번 백그라운드(최대 5초)로 새 버전을 확인해 알린다. 실패하면 조용히 넘어간다. 끄려면
ui.updateNotice = false또는 환경변수EVO_NO_UPDATE_NOTIFIER. - 주소를 임시로 바꾸려면(예: Nexus 호스트 이름이 바뀐 경우) 환경변수
EVO_NEXUS_URL을 설정한다. 재빌드 없이 바로 적용된다. evo update와--check의 접속에는 상한이 있다: TCP 연결 10초, TLS 핸드셰이크 10초, 요청 뒤 응답 헤더 30초. 패킷을 버리는 방화벽에서도 그 안에 오류로 끝난다. 큰 바이너리를 받는 본문 전송에는 상한을 두지 않아, 느린 망에서도 끊기지 않는다.
6. 버전을 건너뛴 업그레이드
섹션 제목: “6. 버전을 건너뛴 업그레이드”기관은 모든 버전을 받지 않아도 된다. 예를 들어 기관 Nexus에 11과 13만 있으면 11을 쓰던 사용자는 evo update로 13으로 바로 올라간다.
- 코드 확인 결과: 설정 파일과 세션 파일에 형식 버전 번호나 버전별 마이그레이션 코드는 없다.
internal/update의migrate는 바이너리 설치 위치를 옮기는 기능이지 데이터 마이그레이션이 아니다. - 그러나 중간 버전(12)에서 설정·세션·저장 형식이 바뀐 적이 있는지는 코드만으로 보증할 수 없다. 건너뛴 업그레이드가 안전한지는 릴리스 담당자가 릴리스 노트의 “직접 업그레이드 가능” 표기로 알린다.
- 릴리스 노트 표기 형식(제안): 각 릴리스 노트에
직접 업그레이드 가능: <최소 버전> 이상한 줄을 둔다. 이 형식은 릴리스 담당자의 결정으로 확정한다(의 Human 결정).
7. 폐쇄망에서 쓸 수 없는 기능
섹션 제목: “7. 폐쇄망에서 쓸 수 없는 기능”- WebSearch: 외부 검색 서비스(brave·tavily)를 직접 쓰는 방식은 쓸 수 없다. 망 안에 검색 중계가 있으면 쓸 수 있다: 모델 provider가
litellm·evomind이면 그 게이트웨이로 자동 중계하고, 다른 모델이면 managed 설정에 중계 주소(web_search.provider: "relay")를 둔다(docs/managed-settings.md). 게이트웨이가 쓰는 검색 백엔드(예: searxng)도 망 안에 있어야 한다. 중계도 provider도 없으면 도구는 외부에 접속하지 않고 안내 오류를 바로 돌려주며, 에이전트가 검색할 수 없다고 알려 준다. - WebFetch: 내부 URL은 정상 동작한다. 외부 URL은 접속 실패한다.
- 첫 실행 모델 선택 메뉴(anthropic, openai, openai-compatible, ollama, litellm) 중 anthropic·openai는 외부 주소이다. 내부 모델 서버는 openai-compatible이나 litellm을 골라 내부
base_url을 입력한다(ollama는 기본localhost주소).
8. 검증 기록
섹션 제목: “8. 검증 기록”| 절차 | 방법 | 결과 |
|---|---|---|
| 기관용 빌드 산출물 구성 | CI job의 빌드 블록을 로컬에서 실행 | dist/A/evo_0.13.0_*, dist/A/sha256sums.txt 생성 |
| 업데이트 종단 | 로컬 서버가 Nexus 검색 API와 evo-bin/<태그>/를 흉내 내는 상태에서, 기관 A용 0.12.0 바이너리가 환경변수 없이 update --check(종료 코드 10, 0.13.0 발견)와 update(0.12.0 → 0.13.0) 수행 |
성공. 서버가 받은 요청은 검색 API, 바이너리, sha256sums.txt뿐이었다(GitLab 접속 없음) |
| 실제 기관 Nexus에 대한 실행 | — | not_run (실제 Nexus 구성·권한은 확인하지 못했다) |
| 반입 설치 3단계(해시 확인, 배치, 버전 확인) | 위 절차를 로컬 폴더에서 수행 | 해시 확인과 --version 출력 확인. 기관 식별자 표시는 #99 반영 후 |
답변은 문서를 근거로 만들지만 틀릴 수 있습니다. 출처 문서를 함께 확인하세요.