Skip to main content

How to Change Settings

What you need to change determines which file you edit and how the change takes effect. First, find your case in the table below.

Directly editing a component's configuration file will be lost at the next startup

The data lake re-renders its configuration at every startup. It reads the templates in plantpulse-datalake-cli/config/templates/, populates ${PP_*}, and then overwrites the configuration locations for each component (such as plantpulse-storage/db/cassandra/conf/cassandra.yaml). Which template goes where is documented on a single page in config/render.map.

Therefore, even if you open and edit cassandra.yaml · postgresql.conf · kafka.properties, they will revert at the next pd start. The place to edit is the template.

# ❌ 이렇게 고치면 다음 기동에 사라진다
vi /opt/kopens/plantpulse-platform/plantpulse-storage/db/cassandra/conf/cassandra.yaml

# ✅ 템플릿을 고친다 — 호스트의 /etc/kopens/conf 가 템플릿 자리로 마운트돼 있다
vi /etc/kopens/conf/cassandra.yaml.template
docker exec plantpulse-datalake pd config render # 렌더해 보고
docker exec plantpulse-datalake pd config diff # 「지금 도는 설정」과의 차이 (0 = 같다)
docker exec plantpulse-datalake pd restart storage # 해당 서비스만 재시작

If pd config diff is not 0, it means the runtime files differ from the template — either someone edited them directly, or the render hasn't been completed yet.

What you want to changeExampleWhere to editHow it takes effect
Passwords · API keysPostgreSQL password, CEP API keybin/passwd.shThe tool does the restart for you
This box's address · identityThe address other boxes connect to, Kafka advertised address, NAT public IP/etc/kopens/platform.node.envbin/restart-datalake.sh
Non-secret values common to all nodesLanguage · timezone, backup schedule switch, console log endpoint/etc/kopens/plantpulse-platform.envbin/restart-datalake.sh
Container resourcesData lake memory limit/etc/kopens/platform.node.env (DOCKER_DATALAKE_MEMORY)bin/restart-datalake.sh
A "line" in engine settingspostgresql.conf parameters, Kafka retention period, Aster TSDB heap/etc/kopens/conf/<파일>.templatebin/restart-datalake.sh or, inside the container, pd config render + pd restart <서비스>
Backup scheduleNightly backup timepd backup schedule set inside the containerImmediately
Public portsPorts opened on the hostcompose/docker-compose.ymlbin/restart-datalake.sh — Caution
Verification after any change is always the same
cd /opt/kopens/plantpulse-platform-docker/bin
./status.sh # 0 = 정상
docker exec plantpulse-datalake pd config diff # 런타임 파일 = 렌더 결과인가 (0 = 같다)
docker exec plantpulse-datalake pd doctor # FAIL 0

1. Passwords · API keys​

Don't open a file. passwd.sh handles the server-side account change → sidecar update → configuration re-render → restart in a single command.

cd /opt/kopens/plantpulse-platform-docker
bin/passwd.sh --list # 바꿀 수 있는 키
bin/passwd.sh PP_PG_PASSWORD # 값은 프롬프트로 (권장)

For details, see Changing Passwords · API Keys.

2. Node file — This box's address and identity​

/etc/kopens/platform.node.env is a file for values that are true only for this box. Do not copy it to another box — once, a box that had copied another box's file was silently reinstalled with the wrong role.

VariableWhen to set itIf left empty
PP_MASTER_IPWhen other boxes (edge, AI, worker) need to connect to this data lake — this host's LAN addressThe address within the compose network (10.99.0.100) — works only within this box
PP_KAFKA_ADVERTISED_HOSTOnly when behind NAT or connecting to Kafka via a second interfaceThe tool will guide you at startup (operator value > PP_MASTER_IP > host's default IP). Usually leave it empty
DOCKER_PP_EXTERNAL_IPPublic IP in a NAT environment. It goes into the TLS certificate SANLeave it empty — if you enter a wrong IP, no certificates will be generated at all
PP_NODE_IDWhen there are multiple boxes, this box's short, unique nameDerived from the container hostname — if there are two boxes, they'll push each other out. Set this before you add a second box
sudo vi /etc/kopens/platform.node.env
# PP_MASTER_IP=192.168.10.20

cd /opt/kopens/plantpulse-platform-docker/bin
./restart-datalake.sh # 데이터레이크만 재생성 + 준비 대기 + 의존 앱 판정
If the advertised address is 127.0.0.1, the render is rejected (exit 8)

If the address a server gives clients to "reconnect here" (Kafka advertised.listeners, Aster TSDB broadcast_rpc_address, Temporal broadcastAddress) is a loopback, the server is fine in place, but every other container will connect to itself. You'll see all port checks UP, yet clients can't connect. The error message tells you which name to fix — it's PP_HOST_IP · PP_MASTER_IP · PP_KAFKA_ADVERTISED_HOST in the node file.

3. Sidecar — Non-secret values common to all nodes​

The sidecar /etc/kopens/plantpulse-platform.env is not just for secrets. Non-secret common values can also be added as a single line VAR=값, and bin/env.sh will read it and pass it to compose. Which variables are available is fully documented with comments in compose/platform.env.example — pick the lines from there and copy them over.

Frequently used ones:

VariableDefaultMeaning
PP_LANGenFor Korean operation, set to ko
PP_TZAsia/SeoulTime series are stored as epoch in this timezone, so keep it for Korean operation
PP_BACKUP_SCHEDULE_ENABLEDtrueIf false, all five backup timers just record "skipped" and do nothing
PP_DATALAKE_ADMIN_LOGS_ENABLEDtrueIf false, only the console's log screen (endpoint) goes down
PP_KEYSPACE · PP_DB_NAME · PP_TOPIC_PREFIXppIdentifiers that the data lake "creates" and the app "reads." Don't change them after installation
sudo vi /etc/kopens/plantpulse-platform.env
# PP_LANG=ko

cd /opt/kopens/plantpulse-platform-docker/bin
./restart.sh # 언어 · 타임존은 앱에도 닿으므로 전체 재시작
Don't touch the first two lines of the sidecar

# generated: and # last rotation: are managed by the tool. The rest of the lines can be VAR=값. Old export VAR=값 lines are still read, but will be rewritten in the new format at the next update.

4. Container memory​

The memory limit of the data lake container is DOCKER_DATALAKE_MEMORY. The default is 96G, and that is the minimum — 64G is not a supported size. It is capped at 90% of host RAM, so a host with less than 107G cannot give it 96G and is below spec (System Requirements). To raise it, put it in the node file.

sudo vi /etc/kopens/platform.node.env
# DOCKER_DATALAKE_MEMORY=128g

cd /opt/kopens/plantpulse-platform-docker/bin
./restart-datalake.sh
If you set it too low, you get the "UP but dead" state

PID 1 inside the container is systemd, so only the Java process gets OOM-killed in the cgroup, and docker ps keeps showing Up. The kill record is only in the host's dmesg. This actually happened on 2026-09-04 with a 64g limit (measured peak 63.9G), and the default was raised to 80G. It was raised again to 96G on 2026-10-04. On 2026-10-29 the container hit the 96G limit and Kafka went down with a memory allocation failure (ENOMEM) — do not lower it below 96G.

dmesg -T | grep -i "memory cgroup"
docker inspect plantpulse-datalake --format '{{.State.OOMKilled}}'

5. Engine configuration "lines" — Templates​

When you're changing lines, not values — like adding a parameter to postgresql.conf or changing Kafka's retention period — edit the host template. Which template becomes which file is listed in Template List.

# 1. 호스트에서 템플릿 편집
sudo vi /etc/kopens/conf/postgresql.conf.template

# 2-a. 데이터레이크 전체 재시작 — 기동 때 자동 렌더
cd /opt/kopens/plantpulse-platform-docker/bin
./restart-datalake.sh

# 2-b. 또는 서비스 하나만 — 컨테이너 안에서
docker exec plantpulse-datalake pd config diff # 무엇이 바뀔지 먼저 본다
docker exec plantpulse-datalake pd config render # 생성물을 실제로 쓴다
docker exec plantpulse-datalake pd restart storage # 그 서비스만 재기동

# 3. 확인
docker exec plantpulse-datalake pd config diff # 0 = 런타임이 렌더 결과와 같다

Just typing pd config render and not restarting is not "applied." The file has only changed. pd restart <서비스> completes the set.

When an image ships new defaults — 3-way seed​

/etc/kopens/conf are host files, so they won't change automatically even if the image brings new defaults. Therefore, the startup tool compares sets per file at each deployment — the current image's defaults, the last deployment's defaults (/etc/kopens/conf.dist), and the host file.

CaseWhat the tool does
File untouched by operator, default changedReplace with the new default
File modified by operator, default also changedKeep the operator file + [WARN] operator edit kept, but THE IMAGE DEFAULT CHANGED + print the diff of default changes
File modified by operator, default unchangedKeep (silently)
Image has a new templateInstall it
Image removes a templateKeep the host file and warn

In the output of restart.sh · update.sh, if you see the [WARN] operator edit kept line, you need to manually merge your edits with the new defaults. The same line tells you where the new default file is.

You can see how your template differs from the image default inside the container.

docker exec plantpulse-datalake pd config diff --templates
# same — 같다
# differs — 호스트 사본이 다르다 (렌더는 이쪽을 쓴다)
# local — 운영자가 추가한 파일
# missing — 이미지엔 있는데 호스트엔 없다

To revert the host directory entirely to the image defaults (the tool keeps a backup in /etc/kopens/conf.backup/<시각>/):

cd /opt/kopens/plantpulse-platform-docker/bin
TEMPLATE_FORCE_SEED=1 ./restart-datalake.sh

6. Backup schedule​

No file editing. Inside the container, pd backup schedule set writes a Quartz cron into the backup_schedule table of the datalake DB — it's the scheduler in plantpulse-datalake-admin-api that reads and executes that table. The "Schedule editor" on the backup screen of the admin console issues the same command.

docker exec plantpulse-datalake pd backup schedule # 지금 일정
docker exec plantpulse-datalake pd backup schedule set --job postgres-diff --calendar "*-*-* 02:45:00"
docker exec plantpulse-datalake pd backup schedule set --job purge --enabled false
docker exec plantpulse-datalake pd backup schedule reset --job postgres-diff # 기본값으로

The five job names are postgres-diff · postgres-full · cassandra-diff · cassandra-full · purge. The calendar follows systemd syntax (*-*-* 02:45:00 daily, Sun *-*-* 01:00:00 Sunday). An invalid expression is rejected without writing anything. Your selection persists in /data1/pp-data/backup/schedule.json, so it survives container recreation → Backup · Restore

7. Public ports​

The ports opened on the host are determined by the plantpulse-datalake service ports: in compose/docker-compose.yml. When changing them, consider two things.

  • The port that listens inside the container is defined by defaults.env (PP_*_PORT) and the template. If you only change the published port, you get a mismatch like "the container binds to 6379, while compose publishes 6399." You must look at both together.
  • 1883 / 1884 (MQTT) are published by the proxy container, not the data lake. If you add the same port to the data lake, startup will fail due to a bind conflict.

See Ports and Services Management for the full port list and firewall.

When changes don't take effect — check in order​

CheckWhat to look for
① Which file winsThe # source: column in bin/env.sh --print. Node file > Sidecar > Shell > Defaults
② Does the name reach the container?Names not written by compose won't get in → Variable Reference
③ Did you recreate the container?Sidecar and node file values are only applied at container recreation. docker restart won't work — use restart-datalake.sh
④ Was it rendered?Is pd config diff 0? If it's 1, restart after pd config render
⑤ Is it a password?File editing won't change it → passwd.sh
⑥ Is the template stale?differs · missing in pd config diff --templates → see 3-way seed above

Don't do this​

  • Don't edit PP_HOME/…/conf/* inside the container. It will disappear at the next startup, and until it does, no one knows which one is the real one.
  • Don't try to apply value changes with docker restart plantpulse-datalake. Environment variables are set when the container is recreated. restart-datalake.sh does that job.
  • Don't use FORCE=1 pd start. It will start another instance on the same port on top of a live process.
  • Don't change PP_KEYSPACE · PP_DB_NAME · PP_TOPIC_PREFIX after installation. A new empty repository will be created under the new name, and the old data will remain under the old name.