跳到主要内容

安装

本页介绍将 PlantPulse Studio 安装到客户一台服务器上的步骤。 它由 4 个 Docker 容器(Web · Server · Builder Sidecar · Docker Proxy)组成,安装脚本 会自动处理从 Docker 安装到启动的所有事项。

PostgreSQL 不在本技术栈中

我们使用的是外部 PG —— 可以复用平台所用的同一个 PG。以前曾经有一种启动捆绑容器的 模式,但现在已经移除了(2026-08-28)—— 实际上曾发生在一台服务器上因使用 5432 端口而发生冲突的事故。

如果是无法连接互联网的隔离网络,请改用 隔离网络安装 而不是本文档。


1. 前置要求​

服务器规格​

项目最低配置推荐配置备注
CPU4 核8 核及以上每个应用会话都会运行构建
内存8 GB16 GB 及以上参见下表
磁盘50 GB 可用空间100 GB 及以上仅容器镜像就约需 6 GB
操作系统Linux (x86_64)RHEL 9 / Rocky 9 / Ubuntu 22.04 及以上只需能运行 systemd + Docker 即可

内存计算依据 —— 这是技术栈固定的上限值。

容器内存上限
studio-server (编排器)2 GB
agent-server (构建器边车)2 GB (可通过 AGENT_SERVER_MEMORY 调整)
studio-web (nginx)256 MB
docker-proxy (Docker 通道)128 MB
每个应用会话容器2 GB

应用会话容器在用户每次打开项目时启动一个,若 30 分钟未使用会自动回收。 请按照同时工作的用户数,额外增加 2 GB 内存。

若目标为 3~5 名并发用户

以 16 GB 内存 · 8 核 · 100 GB 磁盘为基准进行配置,就绰绰有余了。

软件​

  • Docker Engine + Docker Compose v2 (v2.22 或更高版本) 如果未安装,一行安装脚本会自动进行安装。
  • curl、tar (大多数发行版已内置)

端口与防火墙​

技术栈使用 host 网络运行。也就是说,容器端口会直接映射到宿主机上, 因此访问控制只能通过服务器防火墙来实现。

端口用途防火墙
80Studio 界面 (nginx)开放
5171应用监听器 —— 预览 · 部署应用 · 二维码访问开放(必须)
5170Studio APIWeb 内部代理 —— 无需开放(用于诊断)
8000构建器边车 (agent-server)仅限回环 —— 严禁开放
5172MCP 工具桥接仅限回环 —— 严禁开放
2375Docker 守护进程通道 (docker-proxy)仅绑定到 127.0.0.1 —— 技术栈中唯一不使用 host 网络的容器
如果阻止 5171 端口,预览和部署应用将无法打开

预览(/preview/…)和部署应用(/apps/…)由于安全边界的原因,在与 Studio 不同的源(默认 5171 端口)上提供服务。 这是为了阻止通过聊天创建的应用的 JavaScript 访问 Studio 登录 令牌而设置的机制。如果不开放 5171 端口,屏幕将显示为空白。

8000 · 5172 端口没有认证

这两个端口专用于内部组件之间的通信,并且没有认证流程。如果暴露到外部,整个 用户工作区都将可被读写。技术栈默认只绑定到回环地址, 但请绝对不要在防火墙中开放它们。

仓库访问​

镜像从 KOPENS 仓库(docker.kopens.io)获取。安装前请先登录一次。 账户由 KOPENS 运营团队发放。

docker login docker.kopens.io

2. 数据库准备​

Studio 使用外部 PostgreSQL。 可以复用平台所用的同一个 PG。

DATABASE_URL 是必填项

如果为空,安装会在当前位置停止,并提示哪个值为空 —— 我们不会编造一个看似合理的默认值。 因为曾经发生过默认值指向错误位置而导致事故的情况。

DATABASE_URL=postgres://`<user>`:`<password>`@`<db-host>`:5432/`<db-name>`

先创建数据库和账户​

🔴 服务器只对 «已存在» 的数据库执行迁移。它不会创建数据库和角色。 有单独的脚本来负责创建这些。

# .env 의 DATABASE_URL 이 가리키는 DB · 역할을 만든다
bin/provision-platform-db.sh

# 관리자 계정을 따로 줘야 하는 경우
ADMIN_URL=postgres://`<관리자>`:`<password>`@`<호스트>`:5432/postgres bin/provision-platform-db.sh

# 무엇을 할지 보기만 한다
DRYRUN=1 bin/provision-platform-db.sh

AI 部分也遵循相同的规则。


3. 安装(一行命令 · 推荐)​

以 root 用户登录服务器,执行一行命令即可。脚本会完成 Docker 检查/安装 → 下载包 → 生成 .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 \
PS_ANTHROPIC_API_KEY=sk-ant-... \
bash

交互式询问值​

curl -fsSL https://product.kopens.io/plantpulse-studio/install.sh | sudo INTERACTIVE=1 bash
⌨️ 安装到新设备 —— 从头开始到 «Ready» 耗时 2 分 6 秒。这是实际执行过程的录像,连延迟都原样保留(下载镜像的静态部分已折叠)
此画面仅在«新»设备上出现

如果在已安装的服务器上重新执行,由于边车中已有值,会跳过整个交互提示。 上面的画面是干净设备的首次安装。

需要询问的只有五项(自 2026.09 起)。其余七项使用默认值,并在安装结束时打印出这些默认值 —— 并非隐藏,而是展示后跳过。

顺序询问内容变量
1平台 API 服务器 (https://…)PP_API_URL
2平台 API 令牌 (X-API-Key)PP_API_TOKEN
3AI 网关地址 — 需包含 /v1 部分PI_LLM_URL
4AI 网关密钥 (LiteLLM 主密钥)PI_LLM_API_KEY
5AI 模型名称 — 网关中已注册的名称AI_MODEL
请准备好这些值 —— 若缺失,安装将被中止

若必填项为空,安装将停止。 这是为了防止出现“看起来安装已完成但技术栈未启动”的状态而有意为之的行为。不会询问 DATABASE_URL —— PostgreSQL 随技术栈一起提供,安装会自动填充它。

不使用默认值而使用的七项 —— DATA_ROOT(/var/lib/pp-studio) · AI_PROVIDER(openai-compatible) · PP_LANG(en) · PP_TZ(Asia/Seoul) · APPS_PORT(5171) · REGISTRY(docker.kopens.io/ps) · PP_IMAGE_TAG(当前日历版本)。

询问模型名称的原因

如果填写了网关不提供服务的模型名称,就会和使用错误的密钥一样失败。因此从默认值中 移除,并作为询问项提出。

如需更改,可以通过环境变量指定,或使用 PP_ADVANCED=1 运行以询问所有项。

PS_ANTHROPIC_API_KEY 现在不再询问

这是使用云端 Claude 时才需要的值,但由于该产品以网关为前提,实际上所有人都只是按回车 跳过的问项。功能保持不变,有三种方式输入 —— 安装时通过环境变量、 之后通过 bin/passwd.sh PS_ANTHROPIC_API_KEY(省略值则会通过提示符获取,不会留在命令行上)、 或者通过界面上的 设置 > AI。通过 PP_ADVANCED=1 也不会询问。

重新执行也是安全的

在同一台服务器上重新执行安装脚本,只会更新代码,.env 和本地备份(dist/)会被保留。 也可以直接用于升级。

如果安装脚本返回 404 或旧版本

可能是 CDN 缓存残留。请在 URL 后添加 ?v=$(date +%s) 重新下载。

如果提供了错误的值,将在安装前停止​

在接触到机器之前——甚至在安装 Docker 之前——会使用提供的凭证实际调用一次。 平台使用 GET /api/v5/site?limit=1,网关使用 GET /v1/models。

⌨️ 使用错误的网关密钥执行 —— 平台令牌因 401 而被拒绝,安装未启动就停止。后面的 «503» 仅作为警告保留

只有“拒绝”才会停止。 “无法询问”不会停止。

响应判定安装
2xx已接受继续
401 · 403凭证错误中止
400安装脚本的请求错误 —— 产品缺陷,请告知我们中止
5xx · 无法访问无法判定仅警告,继续

未将 5xx 与 401 放入同一列是有意为之 —— 曾发生过负载较高的平台返回 503,而在 3 分钟后 同一个令牌返回了 401 的情况。如果将正在巡检中或比 Studio 启动更晚的网关 误判为“错误密钥”,会导致本应成功的安装被拒绝。

也会同时检查模型名称。 读取网关的 /v1/models 响应,确认 AI_MODEL 是否在该列表中, 如果不存在,则打印出服务中的列表并停止。 如果无法读取列表,则不进行判定 —— 答案为空却声称“不存在”,无异于一项永远不会失败的检查那样的虚假结论。

要跳过检查 —— PP_SKIP_CRED_CHECK=1

这是用于在使用占位符凭证仅测试安装本身时使用的(产品的发布门禁使用此路径)。 在运维安装中启用此值,只是在安装时将首次使用时的失败向后推迟而已。


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/up.sh
配置的权威来源只有一个,即 /etc/kopens/plantpulse-studio.env

环境变量文件不存放在安装目录内,而是放在 repo 树之外的 /etc/kopens/plantpulse-studio.env。权限为 0600。platform · ai · studio 三个产品遵循相同约定使用 /etc/kopens/plantpulse-<product>.env。

安装目录根目录下的 .env 是旧路径。compose 和其余脚本现在都不再读取该文件, 因此修改那里不会改变技术栈。现有安装的 .env 会被 bin/install.sh 移动到新路径(不会新建 —— 如果新建,数据库仍是旧密码,而 env 是新的默认值,会在下次重启时崩溃)。

环境变量主要项目​

项目说明默认值
REGISTRY镜像仓库。清空则只使用本地镜像而不拉取(隔离网络)docker.kopens.io/ps
PP_IMAGE_TAG镜像标签。清空则跟随 VERSION 的日历版本。若需固定,建议使用快照标签(2026.09-20260911)(空值)
DATA_ROOT所有数据(工作区 · 构建 · 状态 · 数据库)的存储路径/var/lib/pp-studio
PLATFORM_API_TARGET委托真实数据和认证的 PlantPulse 平台地址https://192.168.0.41
APPS_PORT应用监听器端口(预览 · 部署应用)5171
PP_LANGWeb 默认语言 ko / enen
PP_TZ时区(IANA ID)。 “今天 · 昨天 · 上周” 的解释依据Asia/Seoul
STUDIO_CORS_ORIGINS仅在其他域调用 API 时指定。默认阻止清空
DATABASE_URL外部 PostgreSQL 连接地址 —— 参考上文第 2 节清空 (必填)
PI_LLM_API_KEY · PP_API_TOKEN 等AI · 平台密钥 —— 参考密钥管理清空 (必填)
账户和角色不会通过环境变量传递

账户不通过环境变量传递。 当服务器没有任何账户时,会在数据库中植入引导管理员,之后在应用的 环境设置 → 用户管理中添加/删除账户并分配角色(管理员 / 构建者 / 查看者)。 请参阅下文 7. 首次登录。

韩国现场请直接填入 PP_LANG=ko

一行安装所生成的 .env 中没有 PP_LANG · PP_TZ 行,因此会应用默认值(en / Asia/Seoul)。 若要以韩文显示,请在 .env 中添加 PP_LANG=ko 并执行 bash bin/restart.sh。

修改 .env 后,必须执行 bin/restart.sh

docker restart 不会重新读取 .env。这就是值未生效却要长时间寻找“为什么没变”的典型陷阱。详细内容请参阅密钥管理。


5. 检查技术栈构成​

安装完成后,应看到容器网络已启动。PostgreSQL 不在此处 —— 我们使用外部 PG。

容器角色
plantpulse-studio-webStudio UI(nginx :80) —— 静态界面 + API 代理
plantpulse-studio-server编排器(:5170) —— 代理 · 会话 · 部署 · 应用监听器(:5171)
plantpulse-studio-agent-server构建器边车 —— 编写应用代码的编码引擎
plantpulse-studio-docker-proxyDocker 守护进程通道。仅对 127.0.0.1 开放
编排器不直接持有 Docker 套接字

docker.sock 不直接挂载到服务器,而是通过 Docker 代理进行访问。 创建和删除会话容器需要守护进程, 但直接给予套接字等同于拥有整个主机的权限。

只有代理不使用 host 网络,而是发布到 127.0.0.1:2375。如果使用 host 网络, 2375 端口将成为一个除了防火墙之外没有任何防护的开放守护进程。

Docker 代理并不是“防止逃逸的边界”

要创建会话容器就需要 POST /containers/create,而能够调用它的一侧,也能够创建挂载了 / 的容器。 代理的控制单位是端点,而不是参数。

这个代理实际上只做两件事 —— 裁剪掉未被使用的 API 接口(卷 · 密钥 · 配置 · Swarm · 节点 · 插件 · 系统事件),以及将守护进程访问集中到一个点,使其可审计。 允许范围被缩小到 studio-server 实际使用的功能(容器 · 镜像 · 构建 · exec · 网络 · 仓库登录)。

因此,请将此技术栈置于信任边界之内。 应将创建应用的人视为对宿主机拥有 权限来进行运维。

此外,当用户打开项目时,应用会话容器会为每个项目启动一个。 它不是技术栈容器,而是服务器在需要时创建,并在空闲 30 分钟后回收。


6. 启动确认​

cd /opt/kopens/plantpulse-studio-docker

bash bin/status.sh # 컨테이너 상태 + 헬스 + 세션 컨테이너 수
curl -s localhost:5170/health

安装完成后,建议立即运行一次综合巡检脚本。它会检查健康状态 · Web 响应 · 实际 登录 · 会话运行时镜像 · 容器状态,只要有一项失败,就会以错误结束。

bash bin/smoke-install.sh
✓ health
✓ client-config → {"lang":"ko",...}
✓ web 200
✓ 로그인(부트스트랩 계정)
✓ 세션 런타임 이미지
✓ 컨테이너 running(...)
✅ 설치 스모크 통과
会话运行时镜像

应用会话容器使用 plantpulse-studio-runtime 镜像。当 bin/up.sh 在本地不存在时 会下载并打标签,但如果失败,会出现 ⚠️ 세션 런타임 이미지 없음 警告,并且打开项目会 失败。此时请检查仓库登录状态并重新执行 bash bin/up.sh。

如果本地已存在,up.sh 不会触碰它 —— 若想更换为新版本, 请参阅 bin/update.sh。


7. 首次登录​

在浏览器中访问 http://<server-ip>/。

当服务器首次启动且没有任何账户时,会在数据库中植入引导管理员。

项目值
用户名admin
密码admin123!

启动日志中也会显示 —— 부트스트랩 관리자 생성: admin — 로그인 후 비밀번호를 바꿀 것。

请首先更改此密码

该值在所有安装中都是一样的。登录后立刻在环境设置 → 用户管理中更改 (密码重置,6 位以上)。修改环境变量文件不会更改 —— 服务器在登录时 按 ①数据库 → ②环境变量 的顺序检查,如果数据库中已有设置,则在此结束。

登录后需要做的事情:

  1. 环境设置 → 用户管理 — 更改引导管理员密码、创建现场用户账户、 分配角色(管理员 / 构建者 / 查看者)
  2. 更改密码 · API 密钥 — 使用 bin/passwd.sh 一次性轮换数据库账户和 AI 密钥。在调试阶段仅需执行一次即可
  3. 环境设置 → AI — 检查 AI 提供商和密钥的连接状态
  4. 环境设置 → 平台 — 检查平台地址和密钥的连接状态(用于真实数据查询)

详细的界面说明请参见快速入门和 环境设置(管理员)。​

8. 日常运维命令​

所有命令均在安装目录(/opt/kopens/plantpulse-studio-docker)下执行。

bash bin/up.sh # 시작(레지스트리에서 최신 이미지 pull 포함). 종료 코드 0 = «준비됨»
bash bin/down.sh # 중지 — 데이터는 그대로 보존, 세션 컨테이너도 정리
bash bin/restart.sh # 재기동(.env 변경 반영)
bash bin/status.sh # 상태 요약
bash bin/logs.sh # 서버 로그 팔로우(기본 studio-server)
bash bin/logs.sh studio-web # 특정 서비스 로그
bash bin/update.sh # 이미지 갱신 + 재기동 → [업데이트](#9-更新)
bash bin/remove.sh # 컨테이너·네트워크 제거. **데이터는 보존이 기본**
旧的名称 start.sh · stop.sh 依然有效

三个产品(Platform · AI · Studio)被统一使用相同的名称和含义的通用动词 —— up · down · restart · status · logs · update · remove。

旧名称没有被删除。bin/start.sh 和 bin/stop.sh 继续执行相同的操作 (CI 会在远程主机上直接调用这些名称)。不需要一次性修改现有的运行手册。

为什么 down.sh 不仅仅调用 compose

Studio 服务器在运行应用时创建的会话容器(plantpulse-studio=1 标签) 不由 compose 管理。 如果仅调用 docker compose down,这些容器会继续运行 —— 这就是“明明已停止,但容器还活着”的情况。down.sh 会一并清理它们。

remove.sh 不会删除数据 —— 若要删除,必须显式指定
bash bin/remove.sh # 컨테이너·네트워크만. 데이터 그대로
bash bin/remove.sh --volumes # 데이터까지 (확인을 묻습니다)
bash bin/remove.sh --volumes --yes # 자동화용 — 묻지 않습니다

这个技术栈的真实数据不在命名卷中,而是在 DATA_ROOT 绑定挂载(默认 /var/lib/pp-studio)中 —— PG 数据 · 工作区 · 构建产物 · 状态。 使用 docker compose down -v 不会删除它们,但运维人员说“删除”时,往往也包含这些。 由于不可恢复,因此仅在明确请求时才处理。

要单独查看会话容器,

docker ps --filter label=plantpulse-studio=1

9. 更新​

bin/update.sh 会重新拉取镜像并重启。重新执行安装脚本,运维脚本也会一起更新(.env · 备份会保留)。

=== "仅更新镜像"

cd /opt/kopens/plantpulse-studio-docker
bash bin/update.sh
仅使用 up.sh(旧称 start.sh)会导致 «会话运行时» 保留旧镜像

up.sh 会拉取 compose 服务的镜像。但是,用户应用实际运行的会话运行时镜像不是 compose 服务,因此不会被子 compose pull 处理, 而 up.sh 仅在该镜像本地不存在时才拉取 —— 如果已存在,则保持原样。

因此,如果只运行 up.sh,其他部分都是新镜像,但只有会话运行时在无声地保留旧版本。 update.sh 与 up.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

下一步​