Skip to main content

Troubleshooting

This document guides you through common issues and solutions for the PlantPulse Platform operated via a one-line / Docker installation. Most issues can be resolved by following the procedures below in order.

There are nine containers

The platform runs as a Docker Compose stack — one certificate one-shot (plantpulse-certs, Exited (0) is normal), one data lake, six apps, one proxy. There is no container named plantpulse-platform.

Narrow down "what is broken" first. ./status.sh answers per service → Installed Shape

First step: Whatever the issue, please check the following 3 things first.

cd /opt/kopens/plantpulse-platform-docker/bin
./status.sh # Container / health / volume summary
./ops-check.sh # Operational health + critical log
./logs.sh -n 200 # Recent container logs (all)

If this doesn't resolve the issue, generate a diagnostic tarball with ./doctor.sh and share it with technical support.

Container Startup Issues

Symptom: Container stuck in unhealthy state and doesn't recover

CauseSolution
Cassandra schema migration failureCheck the error with ./logs.sh cassandra -n 300, then retry with ./restart.sh. If it keeps failing, ./doctor.sh
Data directory permission issueCheck the permissions on the host's /data1/pp-data. sudo chown -R root:root /data1/pp-data && sudo chmod -R 755 /data1/pp-data
Out of memory (OOMKilled)Check with docker inspect <컨테이너> --format '{{.State.OOMKilled}}'. Limit values differ per container — data lake is DOCKER_DATALAKE_MEMORY, apps are DOCKER_SERVER_MEMORY, etc. (Environment Variables)
JVM warm-up incompleteBoot takes 3–5 minutes. If unhealthy persists beyond 5 minutes, proceed to next-level diagnosis
# 어떤 서비스가 비정상인가 (0 = 정상 / 2 = 비정상)
./status.sh

# 스택 전체 준비 판정
./stack-verify-boot.sh

# 컨테이너별 메모리 / CPU
docker stats --no-stream

# 헬스체크 엔드포인트 응답 확인
curl -kfsS https://<server-ip>:4950/api/health | jq
A one-shot container is not a "dead container"

plantpulse-certs bakes certificates and then finishes on its own, so Exited (0) is the success state. Because compose has explicitly disabled the healthcheck for this container (healthcheck: disable), the health column stays blank, and a normally functioning container is never shown as unhealthy. status.sh and ops-check.sh judge only this container by its exit code, so please look at it the same way manually.

Symptom: no such service · reports that the container doesn't exist

The initial installation was not completed, or the container was removed via ./remove.sh.

If you were following an old runbook looking for plantpulse-platform, there is no container by that name — check names with ./status.sh or ./logs.sh --list.

cd /opt/kopens/plantpulse-platform-docker/bin
./install.sh # 최초 설치
# 또는 OS 설정이 이미 끝났다면
./up.sh # 컨테이너 생성 + 기동

Symptom: address already in use (port conflict)

An older version of plantpulse is running natively on the host, or another service is occupying the port.

# 호스트 native plantpulse 정지
pkill -ef plantpulse

# 특정 포트 점유 프로세스 확인 (예: 7500)
ss -tlnp | grep :7500

# 충돌 프로세스를 종료한 후 재시도
./restart.sh

For a detailed port list, see Port and Service Management.

Image / Registry Issues

Symptom: docker pullunauthorized: authentication required

Registry authentication has expired or credentials are missing.

docker login docker.kopens.io
# Username/Password 입력 후
./update.sh

Symptom: Image download failure (network)

# 1. 레지스트리 접근 가능 여부 확인
curl -fsSL https://docker.kopens.io/v2/

# 2. DNS 확인
nslookup docker.kopens.io

# 3. 회사 방화벽 / 프록시 차단 가능성 — 네트워크 관리자에게 다음 도메인 허용 요청
# docker.kopens.io, download.kopens.io

If you're in an air-gapped network, follow the Airgap installation procedure on the Docker Installation page.

Database Issues

Database components run inside the container. Inspection is performed after entering the container with ./shell.sh.

PostgreSQL (meta DB)

Role: Stores platform metadata such as user information, site settings, and asset settings.

./shell.sh # 컨테이너 진입

# 컨테이너 내부에서
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node psql # PostgreSQL 셸 접속
psql=# SELECT 1;
psql=# SHOW max_connections;
psql=# SELECT count(*) FROM pg_stat_activity;
SymptomCauseSolution
Connection refusedPostgreSQL component downRun pd restart storage inside the container. From the host: ./restart.sh
Too many connectionsConnection pool exceededReview the connection pool settings in properties. If temporary, restart storage
Authentication failedPassword mismatchCheck /etc/kopens/plantpulse-platform.env's PP_PG_PASSWORD against the application properties

Path check — The secret sidecar's canonical file is a single /etc/kopens/plantpulse-platform.env (permissions 0600). An old installation may still have a file of the same name under /opt/kopens/, but it is not read, and the installation script restores the canonical file → Environment Variables Reference

Cassandra (time series DB)

Role: Stores large volumes of data such as sensor time series data and alarm history.

./shell.sh

# 컨테이너 내부에서
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node status # 클러스터 상태
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats # 컴팩션 진행 상태
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node cql # CQL 셸 접속
SymptomCauseSolution
Connection timeoutNode downCheck node status with pd node status, then pd restart storage
WriteTimeoutWrite delay (disk I/O saturation)Check pd node compactionstats, run manual compaction with pd node compact
ReadTimeoutRead delay (large partition)Check partition size with pd node table-histograms
Insufficient disk spaceSSTable accumulationRun pd node cleanup, then verify with df -h /data1

Valkey (Redis cache)

./shell.sh

# 컨테이너 내부에서
redis-cli -a "$PP_REDIS_PASSWORD" ping
redis-cli -a "$PP_REDIS_PASSWORD" INFO memory

Login / Console Access Issues

Symptom: Cannot access console from browser

# 1. 컨테이너 health 확인
./status.sh

# 2. 외부 노출 IP 설정 확인
grep DOCKER_PP_EXTERNAL_IP env.sh

# 3. 호스트 방화벽 확인
sudo firewall-cmd --list-ports # RHEL/Rocky/Oracle
sudo ufw status # Ubuntu

# 4. 포트 점유 확인 — 프록시가 80/443 을, 데이터레이크가 7443 을 엽니다
ss -tlnp | grep -E ':(80|443|7443)\s'
SymptomCauseSolution
Page doesn't openplantpulse-proxy is abnormalCheck proxy status with ./status.sh. The proxy is the sole entry point receiving 80/443
Page doesn't openBlocked by firewallRequest that 80, 443, 7443, 4950 be allowed on the company/cloud firewall
Login failsPassword mismatchCheck the default admin / admin123!. If changed, request a reset from the administrator
403 ForbiddenInsufficient user permissionAsk the administrator to check the role
Session expiredAutomatic logout after 30 minutes of inactivityLog in again

Data Collection Issues

Data collection path: OPC server → message broker (Kafka/MQTT) → engine pipeline → Cassandra. If any point in this path is blocked, data will not come in.

Symptom: Data not being collected

Check itemHow to check
OPC connection statusCheck CONNECTED in Web Console > Connection Management > Status
Engine statusCheck RUNNING in Console > Monitoring > System Status
PipelineIf MPS (messages per second) is 0, reception has stopped
Message brokerEnter ./shell.sh and check the Kafka topic with /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node topic
NetworkPing / telnet from OPC server → platform host IP

Symptom: Data delay

CauseSolution
Pipeline queue buildupRaise engine.pipeline.threads in properties
Cassandra write delayCheck pd node compactionstats, monitor disk I/O
Kafka lagCheck consumer lag with pd node topic
Network latencyMeasure RTT between OPC server ↔ platform host

Performance Issues

Symptom: Console / API response is slow

# 호스트에서 컨테이너 자원 사용량
docker stats --no-stream

# 앱 컨테이너의 JVM 메모리 (그 앱이 도는 컨테이너 안에서)
./shell.sh plantpulse-server-web
jmap -heap $(pgrep -f plantpulse-server)
Decide which container first

Since the six apps each run in their own container, you won't find app processes inside the data lake. Identify the target container with ./status.sh, then enter it with ./shell.sh <컨테이너>.

CauseSolution
Container out of memoryRaise the limit for the relevant container, then ./restart.sh — data lake is DOCKER_DATALAKE_MEMORY, apps are DOCKER_SERVER_MEMORY, etc. (Environment Variables)
JVM out of memoryAdjust heap size in setenv inside the container (see Performance Tuning for details)
Frequent GCAnalyze GC logs, tune G1GC options
DB slow queryCheck PostgreSQL slow query logs
Host CPU saturationCheck top / htop, then consider raising DOCKER_PP_CPUS

Symptom: OutOfMemoryError

# 컨테이너 내부에서 heap dump 활성화
./shell.sh
# setenv 또는 JAVA_TOOL_OPTIONS 에 -XX:+HeapDumpOnOutOfMemoryError 추가

# 생성된 hprof 를 호스트로 복사
docker cp plantpulse-datalake:/path/to/heap.hprof /tmp/

Analyze with Eclipse MAT / VisualVM.

Alarm Issues

SymptomCauseSolution
Alarm not triggeringAlarm settings not deployedClick "Deploy" on the alarm settings screen
Duplicate alarmsDuplicate check disabledEnable duplicate check in alarm settings
Email notification not sentSMTP configuration errorCheck mail.properties (inside container: /opt/kopens/plantpulse-platform/plantpulse-server/config/)
No notification soundBrowser autoplay policyAllow site autoplay in browser settings

UI Issues

SymptomSolution
Screen rendering brokenClear browser cache (Ctrl+Shift+Delete)
Chart not displayedCheck JS errors in browser DevTools (F12) > Console
Real-time updates cut offCheck SSE (HTTP streaming) buffering/timeout settings on proxy/firewall
Dashboard fails to loadCheck whether connected tags / data sources exist
Korean text brokenCheck env.sh, PP_LANG=ko, PP_TZ=Asia/Seoul in ./restart.sh, then ./restart.sh

Disk / Volume Issues

Symptom: Insufficient disk space

# 호스트 디스크 사용량
df -h
df -h /data1 # 데이터 디스크

# Docker 사용량 (이미지 / 볼륨 / 빌드 캐시)
docker system df

# 컨테이너 내부 사용량
./shell.sh
df -h
du -sh /opt/kopens/plantpulse-platform/plantpulse-storage/db/cassandra/data
CauseSolution
Accumulated old backupsClean up old tar.gz files under /data1/pp-backup/docker-volume
Unused Docker imagesClean up with docker system prune (images/networks/cache)
Cassandra SSTable accumulationInside container: pd node cleanup, pd node compact
Bloated log directoryClean up /opt/kopens/plantpulse-platform-docker/logs

Caution: docker volume prune deletes all unused volumes. Do not leave a container stopped, as this could accidentally delete the pp-* volume.

Symptom: Volume data recovery needed

Refer to the recovery procedure on the Operations Management - Backup and Recovery page.

Update / Rollback Issues

Symptom: Container doesn't work properly after update

./update.sh automatically rolls back to the previous image if health verification fails. For manual rollback:

# 1. 이전 버전 태그를 env.sh 에 지정
vi env.sh
# PP_IMAGE_TAG="2026.04" ← 이전 안정 버전

# 2. 업데이트 재실행
./update.sh

Symptom: NOT FOUND CONTAINER during update

Initial installation (./install.sh) has not been completed. Please perform the installation first.

Network / Cluster Issues

Symptom: Worker fails to join the master

# 1. 워커 컨테이너 진입 (워커는 기본 스택의 서비스가 아니라 shell.sh 로는 잡히지 않습니다)
docker exec -ti plantpulse-worker-1 /bin/bash
# 워커 내부에서 마스터 IP 로 연결 테스트
ping ${PP_MASTER_IP}

# 2. 마스터에서 링 확인 — 이것이 조인의 «유일한» 증거입니다
cd /opt/kopens/plantpulse-platform-docker/bin
./shell.sh
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node status

# 3. JGroups / Cassandra 포트 (7000, 7001, 7800, 7801, 9042) 방화벽 허용 확인
A running container is not proof of joining

A worker that failed to join reports as normal, exactly like one that succeeded — because the container's own check only looks at "can it reach the master?" In a measurement taken on 2026-08-31, a worker whose Cassandra was OOMKilled kept reporting health: starting even while the ring stayed at 1 node.

Always judge by the ring list from pd node status. For adding workers, bin/worker-add.sh performs this check for you → Cluster Installation

Symptom: MQTT / Kafka external client connection failure

Check that 1883/1884 (MQTT) and 9092/9093/9094 (Kafka) are allowed on both the host firewall and the company/cloud firewall. For a detailed port list, see Port Configuration Information.

  • plantpulse-proxy receives MQTT. Equipment only needs to know this host, and equipment settings don't need to be touched even if the broker moves or is renamed. 1884 is TLS passthrough, so the broker terminates TLS.
  • Kafka does not pass through the proxy. The client reconnects to the advertised.listeners address after bootstrapping — if only bootstrap succeeds and everything after fails silently, suspect this address first.

Emergency Response

When a container is unresponsive

cd /opt/kopens/plantpulse-platform-docker/bin

# 1. 상태 확인
docker ps -a
./status.sh

# 2. 로그에서 마지막 에러 확인
./logs.sh -n 200

# 3. 안전 재시작
./restart.sh

# 4. 위 단계로 회복 안 될 경우 진단 tarball 생성
./doctor.sh
# 생성된 tarball 을 webmaster@kopens.com 으로 전달

If data corruption is suspected

# 1. 즉시 정지 (추가 손상 방지)
./down.sh

# 2. 최신 백업 확인
ls -lh /data1/pp-backup/docker-volume/

# 3. 진단 tarball 생성 (절대 데이터를 임의로 수정하지 마세요)
./doctor.sh

# 4. 기술 지원팀 연락

Prohibited actions in case of data corruption: Do not directly perform pd node repair, pd node cleanup, SSTable deletion, etc. Incorrect recovery operations can expand the damage. Be sure to consult with technical support before proceeding.

Information Needed When Requesting Support

If the above methods don't resolve the issue, sending the following information along with your request enables faster analysis.

ItemHow to collect
Diagnostic tarballFile generated after running ./doctor.sh
Container logs./logs.sh -n 500 > /tmp/container.log 2>&1 (all eight containers)
Per-module logsResult of ./tools/copy-log-to-local.sh (/tmp/plantpulse-log/)
Image versionOutput of ./stack-version.sh
Environment variablesenv.sh (passwords masked)
System informationOS, CPU, memory, disk (uname -a, free -h, df -h)
Error messageExact error message / browser console (F12) capture
Reproduction stepsSequence of actions performed right before the issue occurred

Technical Support: webmaster@kopens.com