Skip to main content

Secret Management

API keys and tokens belong only in the environment variables file. Configuration files (settings.json) are plain text, so if a file leaks, the keys are exposed as-is.

This principle applies from the 2026.07 release onward, and existing installations continue to work (see "Migrating Existing Installations" below).

The single source of truth is /etc/kopens/plantpulse-studio.env

The path of the environment variables file is /etc/kopens/plantpulse-studio.env. It is outside the repo tree, not in the installation directory (/opt/kopens/plantpulse-studio-docker), and its permissions are 0600. The three products — platform · ai · studio — use /etc/kopens/plantpulse-<product>.env with the same convention.

The .env in the installation directory root is the old path. No one reads it now, so editing it won't change the stack. Even if the old file remains, it's only for reference after migration.


The Six Secrets — What and When​

These are the values to put in .env. You can leave keys empty for features you don't use.

Environment VariablePurposeWhen NeededWithout It
PP_API_TOKENPlantPulse platform service keyFor all real-data queries (sites, equipment, tags, alarms)🔴 If empty, refuses to start
PI_LLM_API_KEYOpenAI-compatible gateway keyWhen using the in-house AI gateway (default path)🔴 If empty, refuses to start
PS_ANTHROPIC_API_KEYAnthropic keyWhen AI provider is anthropicAgent doesn't actually work (stub responses)
OPENAI_API_KEYOpenAI keyWhen AI provider is openai〃
GIT_TOKENRemote Git access token (PAT)When pushing app source to customer GitLab/GitHubOnly Git push functionality is unavailable
APP_REGISTRY_TOKENApp image registry tokenWhen pushing deployed apps as Docker imagesOnly image push functionality is unavailable
Different from what you see inside the container

In logs and source, they appear as PLATFORM_API_KEY · AI_API_KEY · ANTHROPIC_API_KEY, but the names you write in .env are the ones above. The reference table is in the "Two Layers of Names" section of Environment Variables Reference.

Only one of the AI keys is needed

You only need one key matching the provider selected in Configuration → AI tab. If you're using the in-house gateway (OpenAI-compatible), it's PI_LLM_API_KEY.


Setting the Keys​

sudo vi /etc/kopens/plantpulse-studio.env
# ── 비밀(키·토큰) — 환경변수 전용 ─────────────────────────
PP_API_TOKEN=...
PI_LLM_API_KEY=...
# PS_ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=
# GIT_TOKEN=
# APP_REGISTRY_TOKEN=
sudo chmod 600 /etc/kopens/plantpulse-studio.env
cd /opt/kopens/plantpulse-studio-docker && bash bin/restart.sh
docker restart doesn't change the key

docker restart plantpulse-studio-server does not re-read .env. When a container is recreated, it just restarts with the old environment variables injected at creation time. This is a classic trap where you change the key and then wonder "why is it still the same?"

You must recreate the container.

bash bin/restart.sh
# 또는
docker compose up -d --force-recreate
Putting it in .env doesn't mean it gets into the container

Only the variables listed in the environment: section of docker-compose.yml are passed to the container. The six above are already wired, but if you add a new variable not in the table, you must also add it to the compose file. (There's a real case where the AI appeared inactive due to a missed variable.)

Verify the Update​

# 서버가 인식한 키 출처 확인 — 부팅 로그
docker logs plantpulse-studio-server 2>&1 | head -40

On the screen, in the Configuration → AI / Platform tab, the key input field should show the 환경변수 기본값 badge, and if you see "Using environment variable value — type to override" in an empty field, it's normal. The input field itself is not locked — the environment variable is the default, and you can override it from the screen.


Priority and Migrating Existing Installations​

PrioritySourceNote
1Value entered from the screen (settings.json)If a value exists, this wins
2Environment variable (/etc/kopens/plantpulse-studio.env)The default set by the installation
This order was «reversed» on 2026-08-23

Before that, the environment variable won. This led to a situation where a dead key in the env would make anything you entered in the Configuration screen ignored, and there was no way to fix it from the screen. The requirement that you should be able to switch AI providers at any time forced this order.

So you don't need to go to the server when a key is dead — entering a new value in the Configuration screen immediately overrides it. If you remember the old order, change your approach here.

The trade-off is that settings.json is plain text (the server enforces 0600, and backup archives are 600/700). If you don't want secrets in a file, leave the screen blank and use only environment variables — that behaves exactly as before.

Even after an upgrade, existing installations won't suddenly break. However, if secrets remain in the file, the boot log will tell you what to migrate (the value never appears in the log; it only shows which item to move to which environment variable).

settings.json 에 비밀이 남아 있습니다 — … platform.apiKey → PLATFORM_API_KEY

The migration process has three steps.

  1. Move the value to the corresponding environment variable in /etc/kopens/plantpulse-studio.env
  2. bash bin/restart.sh
  3. In the Configuration screen, after verifying that the item's badge changes to 환경변수 기본값, delete the old value from settings.json → the boot warning disappears.
settings.json location

<DATA_ROOT>/state/settings.json (default /var/lib/pp-studio/state/settings.json). We recommend backing up before editing, and a restart is required after editing.


Key Rotation​

The Anthropic key and the gateway key have dedicated tools. They update the file and recreate the container in one step, and the values don't end up in your shell history.

cd /opt/kopens/plantpulse-studio-docker
bash bin/backup.sh # ① 되돌릴 지점 확보
bin/passwd.sh PS_ANTHROPIC_API_KEY # ② 값 생략 → 프롬프트로 입력
bash bin/status.sh # ③ 헬스 확인

For detailed usage, see Password · API Key Rotation.

For the rest of the keys (PP_API_TOKEN · OPENAI_API_KEY · GIT_TOKEN · APP_REGISTRY_TOKEN), there's no tool — you edit the file directly.

cd /opt/kopens/plantpulse-studio-docker
bash bin/backup.sh # ① 되돌릴 지점 확보
sudo vi /etc/kopens/plantpulse-studio.env # ② 새 키로 교체
bash bin/restart.sh # ③ 컨테이너 재생성
bash bin/status.sh # ④ 헬스 확인

After rotation, it's best to verify with one chat query (platform key check) and one app build (AI key check).


Automatic Protection​

ItemBehavior
File permissionsAt every server boot, the settings.json · environment variables file is set to 0600, and the state directory is set to 0700
Audit logWhen configuration changes, the changed fields are logged — secrets are shown as a fingerprint (first 8 chars of hash) instead of the value
ScreenKeys managed by environment variables have input disabled, preventing accidental overrides
Key proxyThe platform key exists only in the server and is attached only to authenticated user requests (not to anonymous ones)

Exception — External MCP Server Tokens​

Tokens for external MCP servers, which users add in arbitrary numbers via Configuration → MCP tab, cannot be expressed as environment variables because the count is variable, so they're stored in settings.json. (These are less sensitive than platform/AI keys.)


What You Must Do​

What you must NOT do
  • Do not commit the environment variables file · settings.json to version control (Git). This is why the source of truth is outside the repo tree (/etc/kopens/).
  • Don't paste keys into chat, email, or ticket bodies.
  • Don't share backup archives with unauthorized parties — see the handling precautions in Backup and Recovery.
If you think it's been exposed

From the issuer (platform · AI provider · Git · registry), first revoke it and issue a new key, then follow the "Key Rotation" procedure above. Until the server restarts, the old key remains in memory.