설치 개요
PlantPulse AI 는 docker compose 스택 하나로 돕니다. 정본은
compose/docker-compose.yml 이고, 운영 스크립트도 전부 이 파일을 거쳐 컨테이너를 다룹니다.
curl -fsSL https://product.kopens.io/plantpulse-ai/install.sh | sudo bash
자세한 것은 원라인 설치 를 보십시오. 이 페이지는 무엇이 어디에 깔리는지와 설치 스크립트가 실제로 하는 일을 설명합니다.
어디에 깔리나
/opt/kopens/
├── plantpulse-ai-docker/ ← 설치 본체 (bin · compose)
├── plantpulse-ai-inference-server/ ← 형제 저장소
└── plantpulse-timeseries-insight-server/ ← 형제 저장소
compose/docker-compose.yml 은 두 저장소의 파일을 상대 경로로 bind-mount 합니다(예: 게이트웨이
설정 litellm-config.yaml). 없으면 스택이 뜨지 않습니다 — START=1 이어도 설치기가 기동을 거부하고
빠진 저장소 이름을 찍습니다. 원라인 설치와 폐쇄망 번들은 셋을 함께 받아 풀어 주므로 신경 쓸 일이 없지만,
손으로 git clone 한다면 셋을 형제 디렉터리로 두어야 합니다.
| 무엇 | 어디 |
|---|---|
| 설치 본체 | /opt/kopens/plantpulse-ai-docker |
| 설정·자격증명 정본 | /etc/kopens/plantpulse-ai.env (0600) |
| 그 원본 템플릿 | <설치 본체>/compose/env.gb10.example (AWS g7e 는 env.g7e.example) |
| 하드웨어 프로파일 | <설치 본체>/compose/profiles/gb10.env · g7e.env — GPU 몫. 호스트 env 의 PP_HW_PROFILE 이 고릅니다 |
| 도커 저장 루트 | /data1/docker-data (DOCKER_DATA_DIR 로 변경) |
무엇이 뜨나 — 컨테이너 스물다섯
| 갈래 | 컨테이너 | 하는 일 |
|---|---|---|
| 입구 | plantpulse-proxy | nginx(비root). 호스트의 80 · 443 과 관리 콘솔 HTTPS(5960)를 받아 안으로 넘긴다 |
| 화면 | plantpulse-copilot-web · plantpulse-admin-web | 코파일럿 화면 · 관리 콘솔(HTTP 5959) |
| 추론 | plantpulse-llm · plantpulse-emb · plantpulse-rerank | vLLM — 생성 · 임베딩 · 재순위 |
| 게이트웨이 | plantpulse-litellm (4000) | 모델 호출을 한 곳으로 모은다 |
| 문서 | plantpulse-rag-api · plantpulse-lightrag · plantpulse-docling-serve · plantpulse-document-understanding-api | 문서를 읽고 · 쪼개고 · 찾는다 |
| 지식 | plantpulse-neo4j (7474 · 7687) · plantpulse-qdrant | 지식 그래프 · 벡터 색인 |
| 디지털 스레드 | plantpulse-digital-thread-api (7140, 호스트에 열지 않습니다) · plantpulse-digital-thread-neo4j | 공장 그래프 거울과 커넥터 등록부 · 그 전용 Neo4j(호스트에 열지 않습니다) |
| 시계열 | plantpulse-timeseries-insight-api (8970) · plantpulse-timeseries-insight-server (8980, 호스트에 열지 않습니다) | 이상탐지 · 예측 |
| 시각 | plantpulse-vision-api | 이미지 이해 |
| 관리 | plantpulse-admin-api | 관리 콘솔 백엔드 |
| 관측 | plantpulse-phoenix (6006, 호스트에 열지 않습니다) · plantpulse-dcgm | 트레이스 UI · GPU 지표 |
| 녹취 | plantpulse-asr · plantpulse-asr-audio | 음성 → 글(vLLM Whisper) · 그 오디오 라이브러리를 볼륨에 옮기고 끝나는 일회성 서비스. 영상 · 음성을 켠 설치(PI_MEDIA_ENABLED=true)에서만 뜹니다 → 영상 · 음성 수집 |
| 레지스트리 | plantpulse-registry · plantpulse-registry-ui | 폐쇄망용 내부 이미지 저장소 — 기본 기동에서는 뜨지 않습니다 |
기본으로 뜨는 것은 녹취 둘과 레지스트리 둘을 뺀 스물하나입니다. 영상 · 음성을 켜면 녹취 둘이 더해져 스물셋입니다
(plantpulse-asr-audio 는 할 일을 마치고 «Exited (0)» 으로 남는 것이 정상입니다). 디지털 스레드 둘은 2026.10 에 새로 들어왔습니다.
8970 과 7115 는 MCP 클라이언트가 직접 붙는 자리입니다(플랫폼 CEP 이상탐지, Claude Desktop 같은 것). 나머지는 프록시 뒤에 있습니다.
install.sh 가 하는 일
원라인 설치는 bootstrap.sh 가 저장소를 받아 이 스크립트를 실행하는 것입니다.
OS 를 판별(RHEL 계열 / Debian 계열)한 뒤, 로그에 찍히는 번호대로 처리합니다.
| 단계 | 하는 일 | 호스트 전역 |
|---|---|---|
| 1 | 로케일(ko_KR.UTF-8) · 시간대 — PP_TZ 값을 하나로 정해 호스트 OS 도 그 시간대로 맞춥니다(설치 때 준 값 → 이미 env 에 있던 값 → 호스트 시간대(UTC 가 아니면) → Asia/Seoul) | ✅ |
| 2 | 스왑 해제 (/etc/fstab 에도 반영) | ✅ |
| 3 | Docker CE + buildx + compose v2 플러그인 설치 — 이미 있으면 건너뜁니다 | |
| 3b | NVIDIA 드라이버 + container toolkit 설치, 도커에 nvidia 런타임 등록 (SKIP_GPU=1 이면 건너뜀) | |
| 4 | /etc/docker/daemon.json 과 데이터 디렉터리 (아래) | |
| 5 | OS 튜닝 — chrony · limits · sysctl · tmpfiles | ✅ |
| 6 | 방화벽 개방 — compose 가 실제로 게시하는 포트만 엽니다(SSH 22 는 먼저 열어 둡니다). 그 포트 중 이 스택 밖의 프로세스가 이미 쥔 것을 경고로 찍고, 옮길 수 있는 키를 알려 줍니다 | ✅ |
| 7 | 사내 레지스트리 로그인 확인 (SKIP_LOGIN=1 이면 건너뜀) | |
| 8 | 설정 사이드카 준비 — 템플릿을 /etc/kopens/plantpulse-ai.env 로 복사하고 값을 채운다 → START=1 일 때만 모델 수신 · 이미지 pull · 기동 |
«호스트 전역» 표시가 붙은 단계는 이 제품이 아니라 호스트 전체의 설정을 바꿉니다.
HOST_TUNING 이 이 네 단계를 다룹니다(아래 표).
HOST_TUNING 을 주지 않았는데 이 compose 프로젝트 밖의 컨테이너가 Up 이면 기본이 plan 이
됩니다 — 바뀔 내용만 찍고 아무것도 쓰지 않습니다. 출력을 보고 적용해도 되면
HOST_TUNING=apply 로 다시 돌리십시오. 전용 장비(다른 컨테이너가 없음)면 기본이 apply 입니다.
sysctl 은 호스트에 이미 더 높은 값이 있으면 낮추지 않습니다.
4단계 — 이미 있던 Docker 는 건드리지 않습니다
| 이 호스트의 Docker | 하는 일 |
|---|---|
| 이번 실행이 새로 설치했다 | 기본값(overlay2, DOCKER_DATA_DIR=/data1/docker-data)으로 daemon.json 을 씁니다 |
| 원래 있었다 | 저장소(data-root · storage-driver)는 도는 데몬의 docker info 를 정본으로 보고 새로 쓰지 않습니다. 바뀔 내용은 출력만 하고 재시작하지 않습니다 |
원래 있던 Docker 의 설정을 바꾸고 재시작까지 허용하려면 ALLOW_DOCKER_RECONFIGURE=1 을 줍니다.
다른 DOCKER_DATA_DIR 을 쓰려 할 때도 이것이 필요합니다.
예전에는 기존 daemon.json 에 키가 없으면 기본값을 채워 넣었고, 그 결과 다른 저장소 루트를 쓰던
호스트의 컨테이너와 이미지가 보이지 않게 된 일이 있었습니다. 지금은 그래서 기본이 «건드리지 않음» 입니다.
ALLOW_DOCKER_RECONFIGURE=1 은 그 결과를 이해하고 줄 때만 쓰십시오.
START=1 을 주지 않으면 설정 파일을 만들어 두고 멈춥니다. 값을 확인한 뒤 직접 띄우려는
운영자를 위한 기본값입니다.
자주 쓰는 환경 변수
| 변수 | 뜻 |
|---|---|
START=1 | .env 준비까지 하고 멈추지 않고 기동까지 간다 — 모델 자동 수신과 설치 검증도 이때 돕니다 |
INTERACTIVE=1 | 비어 있는 값을 물어본다 (기본은 비대화식) |
ENV_TEMPLATE | 사이드카의 원본 템플릿. 기본 env.gb10.example(GB10 · arm64), AWS g7e 는 env.g7e.example(amd64). 자동으로 고르지 않습니다 |
ENV_TEMPLATE_SKIP_ARCH_CHECK=1 | 템플릿과 이 기계의 아키텍처가 어긋나면 설치기가 멈춥니다. 새 하드웨어를 시험하는 등 의도한 경우에만 이 검사를 넘깁니다 |
HOST_TUNING | skip · plan · apply — 호스트 전역 설정(로케일 · 시간대 · 스왑 · chrony · limits · sysctl · tmpfiles · 방화벽)과 패키지 설치(Docker CE · NVIDIA 드라이버/toolkit · jq). skip · plan 이면 패키지를 깔지 않고 nvidia 런타임 등록(도커 재시작)도 하지 않습니다 — 할 줄만 찍고, 그것 없이는 못 도는 단계에서 멈춥니다. 기본은 apply, 다른 컨테이너가 도는 호스트면 plan |
DOCKER_DATA_DIR | 이번 실행이 새로 설치하는 도커의 저장 루트 (기본 /data1/docker-data). 원래 있던 Docker 는 자기 루트를 그대로 씁니다 |
ALLOW_DOCKER_RECONFIGURE=1 | 원래 있던(도는) Docker 의 daemon.json 변경 · 재시작을 허용한다 |
SKIP_GPU=1 | 3b단계(NVIDIA 드라이버 · toolkit 설치)를 건너뛴다 — 드라이버를 운영팀이 따로 관리하는 호스트용 |
SKIP_WAIT=1 | START=1 뒤 «응답할 때까지 기다리기» 와 설치 검증을 건너뛴다 |
WAIT_READY_MIN | 위 대기의 상한(분). 기본 15 |
SKIP_LOGIN=1 | 사내 레지스트리 로그인을 건너뛴다 — 폐쇄망용. 이미지 pull 도 함께 건너뛴다 |
SKIP_PULL=1 | 인터넷이 되는 장비에서 이미 받아 둔 이미지로 띄운다 |
INSECURE_REGISTRY | 고객사 내부 레지스트리(HTTP)를 daemon.json 허용 목록에 추가 |
SKIP_PULL=1 은 «옛 빌드로 뜰 수» 있습니다이미지 태그가 YYYY.MM 이고 같은 이름으로 갱신됩니다. 로컬에 캐시된 같은 이름의 태그가
지난달 빌드일 수 있습니다. 버전을 확실히 맞춰야 하면 이 옵션을 쓰지 마십시오.
무엇을 묻고 무엇을 «만드나»
설치기는 사람이나 플랫폼만 아는 값을 묻고, 스택 안에서만 쓰는 비밀은 직접 만듭니다.
| 값 | |
|---|---|
| 묻습니다 | TLS 인증서 SAN(PP_PROXY_CERT_SAN) · 플랫폼 자격증명을 받을 주소와 키(PP_DATALAKE_ADMIN_URL · PP_DATALAKE_ADMIN_API_KEY) — 그다음 남은 자리표시자(플랫폼 API 토큰 · 관리자 비밀번호 · Neo4j 비밀번호 등)를 하나씩 |
| 만듭니다 | 게이트웨이 마스터 키 · 솔트 · 추론 서버 키 · 인바운드 키 · RAG 키 · 관리 세션 비밀 · 저장 자격증명 암호화 키 둘(PI_COPILOT_SECRET_KEY · PI_DT_SECRET_KEY) |
묻는 것은 INTERACTIVE=1 일 때입니다. 묻는 값은 모두 같은 이름의 환경 변수로도 넘길 수 있습니다 —
PP_DATALAKE_ADMIN_URL=… PP_DATALAKE_ADMIN_API_KEY=… PP_API_TOKEN=… PI_ADMIN_PASSWORD=… bash 처럼 주면, 설치기가
아직 자리표시자로 남은 키만 그 값으로 채웁니다(2026.10 재릴리즈 — 예전에는 TLS SAN 과 플랫폼 자격증명 두 값만
받았습니다). 그래도 남은 것은 대화형으로 채우거나 /etc/kopens/plantpulse-ai.env 를 직접 고칩니다. 만드는 값도
자리표시자일 때만 채우고, 사람이 이미 넣은 값은 덮지 않습니다. env 파일에 이미 적힌 TLS SAN 도 다시 설치할 때 그대로 둡니다 — 바꾸려면
PP_PROXY_CERT_SAN=… 을 명시해서 돌립니다.
플랫폼 호스트(PP_HOST)와 플랫폼 PG · Aster TSDB · Redis 계정 · 비밀번호는 더 이상 묻지도 env 에 적지도 않습니다.
플랫폼 호스트는 PP_DATALAKE_ADMIN_URL 의 호스트로 계산되고, 계정 · 비밀번호는 컨테이너와 호스트 스크립트가
시작할 때 플랫폼에서 받습니다. 이 실행에 PP_PG_USER 같은 값을 넘기면 env 에 쓰지 않는다는 경고만 찍습니다.
신뢰 앵커 root.crt 는 설치기가 두지 않으므로 직접 준비합니다 → 아래 「플랫폼 자격증명 받기 — 기동 전에 준비할 것」
프록시의 자기서명 인증서에 사람이 접속할 때 쓰는 주소·이름이 들어 있어야 브라우저가 막지 않습니다. 설치기는 이 호스트의 주소를 기본값으로 잡지만, NAT 바깥의 공인 IP · 로드밸런서 VIP · 도메인 이름은 이 상자에서 보이지 않습니다. 대화형 설치에서는 반드시 묻고, 비대화형이면 호스트 주소로만 잡은 뒤 경고합니다. 바깥 이름으로 접속한다면 쉼표로 여럿 넘기십시오.
curl -fsSL https://product.kopens.io/plantpulse-ai/install.sh \
| sudo PP_PROXY_CERT_SAN=ai.example.com,203.0.113.10 bash
받아 적게 하면 짧고 겹치는 값이 들어옵니다 — 실제로 두 호스트가 문서에 적혀 있던 예시 키를 그대로 함께 쓰고 있던 일이 있었습니다. 지금은 설치기가 만들고, 운영자는 회전만 하면 됩니다.
설치기가 만드는 인바운드 키(PI_INBOUND_API_KEY)는 RAG · 시계열 인사이트 · 문서 이해 · 비전 · 디지털 스레드가 함께
쓰는 입구 키입니다. 비어 있으면 기동 전 판정(bin/lint-env.sh)이 스택을 올리지 않고, 서비스도 각자 기동을 거부합니다 —
키 없이 열린 채 뜨는 길은 개발용 스위치 PI_INBOUND_AUTH_DISABLED=true 를 일부러 줄 때뿐입니다. 손으로 env 를
만들었다면 이 줄을 꼭 채우십시오 → 환경 변수 설정
START=1 일 때 일어나는 일 — 세 가지가 더 있습니다
2026.09 부터 기동 경로가 값을 «받고 · 채우고 · 확인합니다».
| 단계 | 하는 일 |
|---|---|
| 자리표시자 확인 | 🔴 CHANGE_ME_* 나 <PLACEHOLDER> 가 남아 있으면 멈춥니다. 예전에는 경고만 하고 「설치 완료」로 끝났습니다 |
| 플랫폼 자격증명 사전 확인 | 이미지를 받기 전에 플랫폼에서 자격증명을 한 번 받아 봅니다. 키가 틀렸거나 root.crt 가 없으면 [FATAL] [platform-credentials] … 로 아무것도 띄우지 않고 멈춥니다. 두 값이 비어 있어도 멈춥니다 |
| 모델 자동 수신 | 빠진 모델을 model.kopens.ai 에서 받아 SHA256 을 검증한 뒤 풉니다. 예전에는 사람이 따라 하는 절차였습니다 |
| 응답 대기 | 관리 콘솔(:5959/health)과 RAG 관문(:7115/ping)이 답할 때까지 최대 WAIT_READY_MIN(15)분 기다립니다. 넘기면 설치 실패로 끝납니다. 콘솔 HTTPS(:5960)가 답하는지도 찍지만 실패 판정에는 넣지 않습니다 |
| 설치 검증 | 스택이 «떴는지» 가 아니라 «동작하는지» 를 확인합니다(아래) |
자리표시자가 남았는데 기동하면 화면은 멀쩡하고 기능만 죽습니다. 그래서 START=1 이면
기동을 거부합니다. 준비만 하려면 START 를 주지 않으면 됩니다(폐쇄망 설치는 값을 나중에
넣는 흐름 그대로입니다). 2026.10 부터는 나중에 bin/up.sh 로 띄울 때도 같은 검사를 합니다 — 자리표시자가 남아
있으면 남은 키 이름을 찍고 기동을 거부합니다.
클린 설치에서 상태가 전부 running · HTTP 200 인데 셋이 죽어 있던 일이 있습니다 — 셋 다 컨테이너 헬스체크를 통과합니다.
- 모델을 아무도 받지 않아 추론 서버만 재시작을 반복
- 게이트웨이 키가 빈 값이라 모든 채팅이 401
- 플랫폼 토큰이 자리표시자라 MCP 도구가 조용히 0개
설치 검증(bin/verify-install.sh)이 이 셋을 봅니다. 각 검사는 OK · FAIL · 「못 쟀다」 로
답하고, 못 잰 것은 통과로 세지 않습니다.
설치가 «정상» 인지 보는 네 단계
bin/status.sh—21/21 running · HTTP=200(기본으로 뜨는 스물하나)bin/verify-install.sh—OK 4 · FAIL 0. 하나라도 FAIL 이면 설치가 실패로 끝납니다- AI 관리 콘솔 › MCP 게이트웨이 › 서버 — 플랫폼 · 시계열 인사이트 · 디지털 스레드 · 공학 계산 같은 내장 서버가 정상이고 도구 수가 0 이 아니어야 합니다. 0 이면 플랫폼 토큰을 보십시오 → MCP 도구 지도
- 묻기에서 한 번 물어 보십시오 — 1~3 이 모두 초록인데도 채팅만 401 이던 적이 있습니다
- 처음 뜨는 호스트에서는 기동을 두 번 해야 할 수 있습니다. 문서 파서가 의존성 대기 시간 안에 건강해지지 않으면 거기서 멈춥니다. 다시 올리면 21/21 이 됩니다.
- 🔴
docker compose up을 직접 돌리면 배포한 이미지가 되돌아갑니다. 배포는 태그를 그 호출에만 묶고.env에 남기지 않습니다(의도된 동작). 올릴 때는 제공된 스크립트를 쓰십시오.
플랫폼 자격증명 받기 — 기동 전에 준비할 것
2026.10 부터 플랫폼 PG · Aster TSDB · Redis · RustFS 의 계정 · 비밀번호 · 포트는 컨테이너가 기동할 때 플랫폼에서 받습니다(코파일럿 · 시계열 인사이트 API · LightRAG · RAG API · 디지털 스레드 · LiteLLM). compose 는 이 값을 넘기지 않으므로, 아래 넷이 갖춰지지 않으면 그 컨테이너들이 FATAL 로 멈춥니다.
| 준비할 것 | 어디서 |
|---|---|
PP_DATALAKE_ADMIN_URL | https://<플랫폼 호스트>:4950 — 이 호스트가 곧 PP_HOST 입니다 |
PP_DATALAKE_ADMIN_API_KEY | 플랫폼 호스트 /etc/kopens/plantpulse-platform.env 의 같은 이름 줄 |
| 플랫폼 허용목록 | 🔴 AI 호스트의 IP 가 플랫폼 쪽 허용목록에 있어야 받을 수 있습니다 |
/etc/kopens/ca/root.crt | 플랫폼 신뢰 앵커 — 플랫폼 GET /api/credentials/tls 응답의 root_pem. 같은 응답의 root_fingerprint_sha256 과 지문을 대조한 뒤 둡니다 |
/etc/kopens/ca/CA.crt | root.crt 와 같은 내용. 앱이 이 이름으로 읽습니다 |
앞의 두 값은 /etc/kopens/plantpulse-ai.env 에 들어갑니다 — 템플릿에 자리표시자로 들어 있고, 대화형 설치가 묻거나
환경 변수로 넘깁니다. compose 가 /etc/kopens/ca 디렉터리를 통째로 컨테이너에 마운트합니다.
- 두 값은 필수입니다. 비어 있으면 compose 가 기동을 거부하고, 하나만 있으면 컨테이너가 거절합니다.
- 호스트 스크립트(기동 전 DB 프로비저닝 등)도 같은 두 값과
root.crt로 플랫폼에서 받습니다. 호스트 env 에는 플랫폼 계정 · 비밀번호가 없습니다. - 서버 인증서는
root.crt로만 검증합니다 — 파일이 없으면 FATAL 이고 검증을 끄는 길은 없습니다. - 받기에 성공했는지는 로그로 봅니다 — 키 이름과 개수만 찍힙니다.
docker logs plantpulse-copilot-web 2>&1 | grep credentials:
영상 · 음성을 쓰려면 — 설치한 뒤 한 줄
영상 · 음성 수집과 채팅의 음성으로 묻기는 기본으로 꺼져 있습니다. 쓰려면 호스트 env 에 PI_MEDIA_ENABLED=true
한 줄을 넣고 bin/fetch-models.sh 로 녹취 모델(Aura-ASR-Turbo, 약 1.5 GB)을 받은 뒤 bin/restart.sh 합니다.
절차와 확인은 영상 · 음성 수집 에 있습니다.
설치한 뒤에
| 순서 | 하는 일 | 명령 · 문서 |
|---|---|---|
| 1 | 기본 비밀번호를 바꾼다 | 초기 비밀번호 변경 |
| 2 | 스택이 살아 있는지 본다 | bin/status.sh · bin/health.sh |
| 3 | 어디가 막혔는지 짚는다 | bin/doctor.sh |
자주 쓰는 운영 명령은 bin/ 에 있습니다 — up.sh · down.sh · restart.sh ·
logs.sh · backup.sh · update.sh · passwd.sh. 자세한 것은
서비스 운영 을 보십시오.