설치
PlantPulse Studio 를 고객사 서버 한 대에 설치하는 절차입니다. 도커 컨테이너 4종(웹 · 서버 · 빌더 사이드카 · PostgreSQL)으로 구성되며, 설치 스크립트가 도커 설치부터 기동까지 자동으로 처리합니다.
인터넷이 되지 않는 폐쇄망이라면 이 문서 대신 에어갭 설치를 보세요.
1. 사전 요구사항
서버 사양
| 항목 | 최소 | 권장 | 비고 |
|---|---|---|---|
| CPU | 4 코어 | 8 코어 이상 | 앱 세션마다 빌드가 돌아갑니다 |
| 메모리 | 8 GB | 16 GB 이상 | 아래 표 참조 |
| 디스크 | 50 GB 여유 | 100 GB 이상 | 컨테이너 이미지만 약 6 GB |
| OS | Linux (x86_64) | RHEL 9 / Rocky 9 / Ubuntu 22.04 이상 | systemd + 도커가 돌면 됩니다 |
메모리 산정 근거 — 스택이 고정으로 잡는 상한값입니다.
| 컨테이너 | 메모리 상한 |
|---|---|
| studio-server (오케스트레이터) | 2 GB |
| agent-server (빌더 사이드카) | 2 GB |
| studio-web (nginx) | 256 MB |
| postgres (번들 모드) | 제한 없음(실사용 수백 MB) |
| 앱 세션 컨테이너 1개당 | 2 GB |
앱 세션 컨테이너는 사용자가 프로젝트를 열 때마다 하나씩 뜨고, 30분간 쓰지 않으면 자동 회수됩니다. 동시 작업자 수만큼 2 GB 를 더해 잡으세요.
16 GB 메모리 · 8 코어 · 100 GB 디스크를 기준으로 잡으면 여유롭습니다.
소프트웨어
- Docker Engine + Docker Compose v2 (v2.22 이상) 설치되어 있지 않으면 원라인 설치 스크립트가 자동으로 설치합니다.
curl,tar(대부분의 배포판에 기본 포함)
포트와 방화벽
스택은 host 네트워크로 동작합니다. 즉 컨테이너 포트가 호스트에 그대로 열리므로, 접근 통제는 오직 서버 방화벽으로만 이뤄집니다.
| 포트 | 용도 | 방화벽 |
|---|---|---|
| 80 | 스튜디오 UI (nginx) | 개방 |
| 5171 | 앱 리스너 — 프리뷰 · 배포앱 · QR 접속 | 개방(필수) |
| 5170 | 스튜디오 API | 웹이 내부 프록시 — 개방 불필요(진단용) |
| 5432 | PostgreSQL(번들 모드) | 127.0.0.1 로만 바인드 — 개방 금지 |
| 8000 | 빌더 사이드카(agent-server) | 루프백 전용 — 절대 개방 금지 |
| 5172 | MCP 도구 브리지 | 루프백 전용 — 절대 개방 금지 |
프리뷰(/preview/…)와 배포앱(/apps/…)은 보안 경계 때문에 스튜디오와 다른 오리진
(기본 5171 포트)에서 서빙됩니다. 채팅으로 만든 앱의 자바스크립트가 스튜디오 로그인
토큰에 접근하지 못하게 하는 장치입니다. 5171 을 열지 않으면 화면이 비어 보입니다.
두 포트는 내부 부품 간 통신 전용이며 인증 절차가 없습니다. 외부에 노출되면 전체 사용자 워크스페이스를 읽고 쓸 수 있게 됩니다. 스택은 기본적으로 루프백에만 바인드하지만, 방화벽에서도 절대 열지 마세요.
레지스트리 접근
이미지는 KOPENS 레지스트리(docker.kopens.io)에서 받습니다. 설치 전에 한 번 로그인하세요.
계정은 KOPENS 운영팀이 발급합니다.
docker login docker.kopens.io
2. 데이터베이스 선택
설치 전에 둘 중 하나를 정하세요. 나중에 바꿀 수도 있지만 데이터 이관이 필요합니다.
=== "(A) 번들 PostgreSQL — 기본"
스택이 PostgreSQL 컨테이너를 함께 띄웁니다. 별도 DB 서버가 없는 현장의 기본값입니다.
COMPOSE_PROFILES=bundled-pg
PG_DB=ppstudio
PG_USER=ppstudio
PG_PASSWORD=`<충분히 긴 임의 문자열>`
데이터는 DATA_ROOT/postgres 아래에 저장됩니다.
=== "(B) 외부·공용 PostgreSQL"
플랫폼용 PostgreSQL 이 이미 있는 현장이라면 이중 인프라를 없앨 수 있습니다.
COMPOSE_PROFILES 줄을 지우고 접속 URL 만 지정하면 PostgreSQL 컨테이너가
아예 뜨지 않습니다.
# COMPOSE_PROFILES 줄 삭제
DATABASE_URL=postgres://`<사용자>`:`<비밀번호>`@`<DB호스트>`:5432/`<DB명>`
빈 데이터베이스만 준비하면 됩니다 — 테이블은 서버가 처음 뜰 때 자동으로 만듭니다.
번들 모드에서 데이터가 이미 쌓인 뒤 PG_PASSWORD 만 바꾸면, 기존 데이터 디렉터리의
계정과 어긋나 스택이 뜨지 않습니다. 비밀번호를 바꾸려면 PostgreSQL 안에서 계정
비밀번호를 먼저 변경해야 합니다.
3. 설치 (원라인 · 권장)
서버에 root 로 접속해 한 줄을 실행합니다. 스크립트가 도커 확인·설치 → 패키지 내려받기 →
.env 생성 → 스택 기동까지 수행합니다.
curl -fsSL https://product.kopens.io/plantpulse-studio/install.sh | sudo bash
설치 위치는 /opt/kopens/plantpulse-studio-docker 이고, 이후 모든 운영 명령은 이 디렉터리에서
실행합니다.
값을 미리 정해 무인 설치
환경변수는 bash 앞에 붙여야 파이프를 타고 전달됩니다.
curl -fsSL https://product.kopens.io/plantpulse-studio/install.sh \
| sudo PLATFORM_API_TARGET=https://192.168.0.41 \
DATA_ROOT=/data1/pp-studio \
ANTHROPIC_API_KEY=sk-ant-... \
bash
값을 물어보게 하기
curl -fsSL https://product.kopens.io/plantpulse-studio/install.sh | sudo INTERACTIVE=1 bash
빈 항목마다 프롬프트가 뜹니다(데이터 루트 · PG 비밀번호 · 플랫폼 주소 · 관리자 계정 등).
같은 서버에서 설치 스크립트를 재실행하면 코드만 갱신되고 .env 와 로컬 백업(dist/)은
보존됩니다. 업그레이드 용도로 그대로 써도 됩니다.
CDN 캐시가 남아 있을 수 있습니다. URL 뒤에 ?v=$(date +%s) 를 붙여 다시 받으세요.
4. 설치 (수동)
패키지를 이미 받아 놓았거나 .env 를 직접 작성하려는 경우입니다.
cd /opt/kopens/plantpulse-studio-docker
sudo cp .env.example /etc/kopens/plantpulse-studio.env
sudo vi /etc/kopens/plantpulse-studio.env # 아래 표를 보고 값 채우기
sudo chmod 600 /etc/kopens/plantpulse-studio.env
bash bin/start.sh
/etc/kopens/plantpulse-studio.env 하나다환경변수 파일은 설치 디렉터리 안이 아니라 repo 트리 밖인
/etc/kopens/plantpulse-studio.env 에 둡니다. 권한은 0600 입니다. platform · ai · studio
세 제품이 같은 규약으로 /etc/kopens/plantpulse-<제품>.env 를 씁니다.
설치 디렉터리 루트의 .env 는 옛 경로입니다. compose 도 나머지 스크립트도 이제 그
파일을 읽지 않으므로, 거기를 고쳐도 스택은 바뀌지 않습니다. 기존 설치의 .env 는
bin/install.sh 가 새 경로로 옮겨 줍니다(새로 만들지 않습니다 — 새로 만들면 DB 는 옛
비밀번호인데 env 는 새 기본값이 되어 다음 재기동에서 죽습니다).
환경변수 주요 항목
| 항목 | 설명 | 기본값 |
|---|---|---|
REGISTRY | 이미지 레지스트리. 비우면 pull 없이 로컬 이미지만 사용(에어갭) | docker.kopens.io/ps |
TAG | 이미지 태그. 특정 버전 고정 시 2026.08 처럼 지정 | latest |
DATA_ROOT | 모든 데이터(워크스페이스 · 빌드 · 상태 · DB)가 저장될 경로 | /var/lib/pp-studio |
PLATFORM_API_TARGET | 실데이터·인증을 위임할 PlantPulse 플랫폼 주소 | https://192.168.0.41 |
APPS_PORT | 앱 리스너 포트(프리뷰·배포앱) | 5171 |
PP_LANG | 웹 기본 언어 ko / en | en |
PP_TZ | 타임존(IANA ID). "오늘 · 어제 · 지난주" 해석 기준 | Asia/Seoul |
STUDIO_CORS_ORIGINS | 다른 도메인에서 API 를 부를 때만 지정. 기본은 차단 | 비움 |
COMPOSE_PROFILES / DATABASE_URL | 데이터베이스 선택 — 위 2절 참조 | bundled-pg |
ANTHROPIC_API_KEY 등 | AI · 플랫폼 키 — 비밀 관리 참조 | 비움 |
STUDIO_LOCAL_USERS · STUDIO_ADMINS · STUDIO_VIEWERS 는 없어졌습니다(2026-08-18).
서버가 계정이 하나도 없을 때 부트스트랩 관리자를 DB 에 심고, 그 뒤로는 앱의
환경설정 → 사용자 관리에서 계정을 추가·삭제하고 역할(관리자 / 빌더 / 뷰어)을 줍니다.
아래 7. 첫 로그인 참조.
PP_LANG=ko 를 직접 넣으세요원라인 설치가 만드는 .env 에는 PP_LANG · PP_TZ 줄이 없어 기본값(en / Asia/Seoul)이
적용됩니다. 한국어로 띄우려면 .env 에 PP_LANG=ko 를 추가하고 bash bin/restart.sh.
.env 를 고친 뒤에는 반드시 bin/restart.shdocker restart 는 .env 를 다시 읽지 않습니다. 값이 반영되지 않은 채로 "왜 안 바뀌지"를
한참 찾게 되는 대표적인 함정입니다. 자세한 내용은 비밀 관리에 있습니다.
5. 스택 구성 확인
설치가 끝나면 컨테이너 4종이 떠 있어야 합니다.
| 컨테이너 | 역할 |
|---|---|
pp-studio-web | 스튜디오 UI(nginx :80) — 정적 화면 + API 프록시 |
pp-studio-server | 오케스트레이터(:5170) — 에이전트 · 세션 · 배포 · 앱 리스너(:5171) |
pp-studio-agent-server | 빌더 사이드카 — 앱 코드를 작성하는 코딩 엔진 |
pp-studio-postgres | 번들 PostgreSQL (외부 DB 를 쓰면 뜨지 않습니다) |
여기에 더해, 사용자가 프로젝트를 열면 앱 세션 컨테이너가 프로젝트마다 하나씩 뜹니다. 스택 컨테이너가 아니라 서버가 필요할 때 만들고 유휴 30분 후 회수합니다.
6. 기동 확인
cd /opt/kopens/plantpulse-studio-docker
bash bin/status.sh # 컨테이너 상태 + 헬스 + 세션 컨테이너 수
curl -s localhost:5170/health
설치 직후에는 종합 점검 스크립트를 한 번 돌리는 것을 권장합니다. 헬스 · 웹 응답 · 실제 로그인 · 세션 런타임 이미지 · 컨테이너 상태를 모두 검사하고, 하나라도 실패하면 오류로 끝납니다.
bash bin/smoke-install.sh
✓ health
✓ client-config → {"lang":"ko",...}
✓ web 200
✓ 로그인(부트스트랩 계정)
✓ 세션 런타임 이미지
✓ 컨테이너 running(...)
✅ 설치 스모크 통과
앱 세션 컨테이너는 plantpulse-studio-runtime 이미지를 씁니다. bin/start.sh 가 자동으로
내려받아 태그하지만, 실패하면 ⚠️ 세션 런타임 이미지 없음 경고가 뜨고 프로젝트 열기가
실패합니다. 이때는 레지스트리 로그인 상태를 확인하고 bash bin/start.sh 를 다시 실행하세요.
7. 첫 로그인
브라우저에서 http://<서버IP>/ 로 접속합니다.
계정이 하나도 없는 상태에서 서버가 처음 뜨면 부트스트랩 관리자를 DB 에 심습니다.
| 항목 | 값 |
|---|---|
| 아이디 | admin |
| 비밀번호 | admin123! |
부팅 로그에도 남습니다 — 부트스트랩 관리자 생성: admin — 로그인 후 비밀번호를 바꿀 것.
모든 설치에서 같은 값입니다. 로그인하자마자 환경설정 → 사용자 관리에서 바꾸세요 (비밀번호 재설정, 6자 이상). 환경변수 파일을 고치는 것으로는 바뀌지 않습니다 — 서버는 로그인할 때 ①DB → ②환경변수 순으로 보고 DB 에서 잡히면 거기서 끝냅니다.
로그인 후 할 일:
- 환경설정 → 사용자 관리 — 부트스트랩 관리자 비밀번호 변경, 현장 사용자 계정 생성, 역할(관리자 / 빌더 / 뷰어) 지정
- 비밀번호 · API 키 변경 — DB 계정과 AI 키를
bin/passwd.sh로 한 번에 회전. 커미셔닝 때 한 번만 하면 됩니다 - 환경설정 → AI — AI 프로바이더와 키 연결 상태 확인
- 환경설정 → 플랫폼 — 플랫폼 주소·키 연결 확인(실데이터 조회에 필요)
자세한 화면 설명은 시작하기와 환경설정(관리자)에 있습니다.
8. 일상 운영 명령
모든 명령은 설치 디렉터리(/opt/kopens/plantpulse-studio-docker)에서 실행합니다.
bash bin/start.sh # 시작(레지스트리에서 최신 이미지 pull 포함)
bash bin/stop.sh # 중지 — 데이터는 그대로 보존, 세션 컨테이너도 정리
bash bin/restart.sh # 재기동(.env 변경 반영)
bash bin/status.sh # 상태 요약
bash bin/logs.sh # 서버 로그 팔로우(기본 studio-server)
bash bin/logs.sh studio-web # 특정 서비스 로그
세션 컨테이너만 따로 보려면,
docker ps --filter label=plantpulse-studio=1
9. 업데이트
bin/start.sh 는 레지스트리에서 이미지를 다시 받아 갱신합니다. 설치 스크립트를 다시
실행하면 운영 스크립트까지 함께 갱신됩니다(.env · 백업은 보존).
=== "이미지만 갱신"
cd /opt/kopens/plantpulse-studio-docker
bash bin/start.sh
=== "패키지까지 갱신"
curl -fsSL https://product.kopens.io/plantpulse-studio/install.sh | sudo bash
버전 고정
버전 표기는 YYYY.MM 형식입니다(예: 2026.08). 자동 갱신을 원치 않는 운영 환경에서는
.env 에 태그를 고정하세요.
TAG=2026.08
bash bin/backup.sh 를 먼저 돌려 두세요. 절차는 백업과 복구에 있습니다.
이미지 서명 검증(선택)
배포된 이미지가 KOPENS 가 서명한 것인지 확인할 수 있습니다. cosign 이 설치돼 있어야 합니다.
cd /opt/kopens/plantpulse-studio-docker
bash bin/verify-images.sh
[verify] ✅ docker.kopens.io/ps/plantpulse-studio-server:2026.08
[verify] ✅ docker.kopens.io/ps/plantpulse-studio-web:2026.08
[verify] ✅ docker.kopens.io/ps/plantpulse-studio-runtime:2026.08
다음 단계
- 비밀 관리 — AI · 플랫폼 키를 안전하게 넣는 방법
- 도메인과 리버스 프록시 — IP 대신 도메인·HTTPS 로 서비스하기
- 백업과 복구 — 자동 백업 설치와 복구 리허설
- 트러블슈팅 — 증상별 원인·조치표