Where is the configuration file
Data lake configuration is built from «two sources, one direction». The files that operators edit are fixed, and the configuration files inside the container are what get generated by multiplying those together.
호스트 /etc/kopens/conf/*.template ← 설정의 «형태» (빈칸이 뚫린 원본)
× /etc/kopens/plantpulse-platform.env ← 시크릿 (비밀번호 · API 키)
× /etc/kopens/platform.node.env ← 이 노드의 값 (IP · 모드)
+ 이미지 안 config/defaults.env ← 비밀 아닌 기본값 (위에서 안 준 것만)
─────────────────────────────────────────
→ pd config render → /opt/kopens/plantpulse-platform/<module>/conf/… (생성물)
pd start is rendered first, without exception, every time. So even if you hand-edit the generated files inside the container, they disappear on the next startup. On 2026-09-01, there was an actual incident where someone edited cassandra.yaml inside the container to enable authentication, and then a regeneration reverted the file, breaking authentication entirely.
The four canonical files
| # | File | What it holds | Format | Who writes it |
|---|---|---|---|---|
| 1 | /etc/kopens/plantpulse-platform.env | Secrets — service account passwords, API keys, TLS passwords. Non-secret common values may also be written here | One per line in VAR=값, without export. The two header lines (# generated: · # last rotation:) are managed by the tool | Created by install.sh, updated by passwd.sh. Non-secret lines are edited directly by the operator |
| 2 | /etc/kopens/platform.node.env | Values true only for this box — PP_MASTER_IP · PP_KAFKA_ADVERTISED_HOST · DOCKER_PP_EXTERNAL_IP · PP_NODE_ID | Same format | Created from a template by the installer, and edited directly by the operator |
| 3 | /etc/kopens/conf/*.template | The shape of the configuration — 33 original configuration files for each engine | Each engine's own syntax + ${PP_변수} placeholders | Seeded from the image on first startup, then edited directly by the operator |
| 4 | (inside the image) plantpulse-datalake-cli/config/defaults.env | Non-secret defaults — port, account name, directory, TLS settings | KEY=value | Product-provided. Operators don't edit this directly but override it with 1 and 2 |
Editing the password line on the sidecar alone does not complete the change. For values where the server account is the source of truth, such as PostgreSQL and Cassandra, the server side must also be changed, and doing this out of order will prevent the platform from starting. bin/passwd.sh performs that sequence for you → Changing Passwords / API Keys
The order in which values are determined
The order in which the host's bin/env.sh reads things from top to bottom is the priority order. What is read later wins.
| Priority | Source | Why it wins |
|---|---|---|
| 1 (highest) | /etc/kopens/platform.node.env | An unconditional assignment read after the sidecar |
| 2 | /etc/kopens/plantpulse-platform.env | An unconditional assignment in VAR=값 — also overrides the shell's export |
| 3 | The calling shell's export | Only when 1 and 2 don't specify that name |
| 4 (lowest) | ${VAR:-기본값} of bin/env.sh | Only when no one has set it |
That value flows through compose into the container as an environment variable, and inside the container the value passed in overrides defaults.env.
export is silently ignoredMethods of supplying a value from the shell, such as PP_PG_PASSWORD=새값 bin/up.sh, only work on a node that doesn't yet have a sidecar. If the sidecar already holds that name, the sidecar wins. There have been actual incidents where someone believed the value had been changed this way and moved on.
To see the effective value and its source for this box right now, don't try to simulate it in your head — run this command instead. Secrets are masked with ****.
cd /opt/kopens/plantpulse-platform-docker
bin/env.sh --print
There is no sidecar inside the container
The /etc/kopens/plantpulse-platform.env file is not mounted into the container. Values only get in through the path where the host's bin/env.sh reads the sidecar and compose injects that as an environment variable into the container.
This has two consequences.
- After editing the sidecar, the container must be recreated for the new value to take effect. The host's
bin/restart-datalake.shdoes this. - No matter what you write in the sidecar, a name that compose doesn't pass through never reaches the container. Which names reach it is determined by the
x-pp-secretsanchor incompose/docker-compose.ymland theenvironment:block of theplantpulse-datalakeservice. The Variable Reference collects only the «names that reach».
If you run pd doctor inside the container, the sidecar row doesn't show up as "file not found" — it doesn't show up at all. Instead, the all required secrets set row is the actual measurement — this is expected.
Template list — what renders where
The 33 templates in the host's /etc/kopens/conf/ (23 top-level + 10 cluster/) go to the locations below. The source of truth for the mapping table is plantpulse-datalake-cli/config/render.map inside the container, and pd config list prints the row corresponding to this node's mode.
| Template | Render location (relative to PP_HOME) | MASTER | WORKER |
|---|---|---|---|
valkey.conf | plantpulse-storage/cache/valkey/conf/valkey.conf | ○ | ○ (cluster/) |
postgresql.conf · pg_hba.conf | plantpulse-storage/db/postgres/conf/ | ○ | ○ (cluster/) |
cassandra.yaml · jvm-server.options | plantpulse-storage/db/cassandra/conf/ | ○ | ○ (cluster/) |
spark-env.sh · spark-defaults.conf · metrics.properties | plantpulse-analytics/spark/conf/ | ○ | ○ |
hive-site.xml · hive-auth.properties | plantpulse-analytics/spark/conf/ | ○ | ○ (cluster/) |
hive-site.xml | plantpulse-analytics/hive/conf/hive-site.xml | ○ | — |
kyuubi-defaults.conf | plantpulse-analytics/kyuubi/conf/ | ○ | ○ |
gravitino-iceberg-rest-server.conf | plantpulse-analytics/gravitino/conf/ | ○ | — |
kafka.properties · kafka-jaas.conf | plantpulse-messaging/kafka/config/kafka.properties · jaas.conf | ○ | — |
hivemq.xml · plantpulse-mq-auth.properties | plantpulse-messaging/mqtt/conf/config.xml · auth.properties | ○ | — |
plantpulse-timeseries-engine.conf | plantpulse-timeseries/engine/conf/ (under two names) | ○ | — |
plantpulse-datalake-admin-api.properties | plantpulse-datalake-admin-api/config/ | ○ | ○ (cluster/) |
workflow.yaml · application.yaml | plantpulse-workflow/temporal/config/ · kestra/config/ | ○ | — |
plantpulse-cep.properties | plantpulse-cep/config/ | ○ | — |
plantpulse-jdbc.properties · plantpulse-data-gateway.properties | plantpulse-data-gateway/config/ | ○ | — |
The cluster/ mark means the WORKER node uses a different template under /etc/kopens/conf/cluster/. For example, MASTER's valkey.conf.template has no replicaof, while cluster/valkey.conf.template has replicaof ${PP_MASTER_IP} ${PP_REDIS_PORT}.
Template syntax
There are only three.
| Syntax | Meaning |
|---|---|
${PP_VAR} | If the value is missing, the entire render fails (exit 4). It will not proceed by filling in an empty value |
${PP_VAR:기본값} · ${PP_VAR:-기본값} | If the value is missing, use the default |
Secrets cannot have inline defaults. There was an incident where the old renderer filled in an empty value and proceeded, resulting in Cassandra coming up with an empty-string password, so it now lists all missing names and halts instead.
Configuration that isn't rendered — the management console account
The management console's login account is not part of any template. The admin-api process reads it directly from environment variables. This is to avoid creating one more copy of the password on disk.
| Variable | Where it comes from | Default |
|---|---|---|
PP_DATALAKE_ADMIN_USER | defaults.env | admin |
PP_DATALAKE_ADMIN_PASSWORD | sidecar | Installs from 2026-09-05 onward use the same development default as the web console admin → Changing the initial password. Installs before that date have this empty, so the console is disabled |
PP_DATALAKE_ADMIN_API_KEY | sidecar | None — if empty, only key authentication is disabled; browser login still works |
Differences from old guidance
| Old documentation | Now |
|---|---|
configure.sh generates the configuration | pd config render (and pd start every time) |
/etc/kopens/conf is mounted as plantpulse-startup/template | Mounted as plantpulse-datalake-cli/config/templates (2026-09-03). The old location was a copy that nothing reads, so operator edits there never reached the render |
env.sh · env-reset.sh inside the container | Removed. Values are decided by the host and passed in by compose |
Disabling a component with PP_OPTIONS | The variable name changed to PD_OPTIONS, and the current compose stack does not pass this value into the container → FAQ |
PP_TIER (FULL / DATALAKE / APP) | Removed on 2026-09-02. Every box is a full install |
Related documents
- How to change configuration — actual procedure
- Variable Reference
- Path map