Skip to main content

Container Mode Operations Guide

From the 2026.05 release onward, PlantPulse Edge ships as a single Docker container. This page consolidates day-to-day operations and troubleshooting for container mode in one place.

native mode

For boxes on the existing native deployment (installed directly on the system), keep using the native pages in the left-hand menu, such as 시작 (start.sh), 중지 (stop.sh), and 재시작 (restart.sh). This page applies only to container deployments (boxes where systemctl status plantpulse-edge.service is active).

Container vs native — where is it running?

# 컨테이너 모드면 active
systemctl is-active plantpulse-edge.service

# 또는 직접 확인
curl -ks https://127.0.0.1/api/v1/system/version | grep container_mode

container_mode=true → container mode. If container_mode=false or the endpoint does not respond, it is native.

One-line status check

sudo bash /opt/kopens/install/bin/status.sh

Output items:

  • Container: name / image / image_tag / state / health / started time
  • Resources: CPU usage / MEM usage / PID count
  • Listening ports: 10 ports (80, 443, 1883, 1884, 6379, 7799, 9042, 1880, 12000, 12443)
  • App.properties key settings (edge.id / site_id / dev.mode / mqtt.enable / sparkplug.enable)
  • API: /api/v1/system/version + /api/v1/system/health response + HTTP code
  • Upgrade status: contents of /etc/kopens/upgrade.status (idle/running/success/...)

Day-to-day operations commands

TaskCommand
Check statusbash /opt/kopens/install/bin/status.sh
Health (exit-code based)bash /opt/kopens/install/bin/health.sh
View logsbash /opt/kopens/install/bin/logs.sh tomcat (or cassandra/mqtt/redis/node-red/api/catalina)
Follow logsbash /opt/kopens/install/bin/logs.sh -f tomcat
Shell inside the containerbash /opt/kopens/install/bin/shell.sh
Change settingsbash /opt/kopens/install/bin/config.sh --set <key> <value>
Restartsudo systemctl restart plantpulse-edge.service
Backupsudo bash /opt/kopens/install/bin/backup.sh
Restoresudo bash /opt/kopens/install/bin/restore.sh <archive>
Collect diagnostics (escalation)sudo bash /opt/kopens/install/bin/doctor.sh
OTA upgradesudo bash /opt/kopens/install/upgrade.sh

Health check API

/api/v1/system/version — no authentication required

{
"data": {
"product_name": "PlantPulse Edge",
"version": "2026",
"build_date": "20260523",
"image_tag": "2026-20260523",
"container_mode": true
},
"meta": {
"timestamp": 1778925572946,
"request_id": "..."
}
}

Primary uses: OTA upgrade verification, fleet inventory for monitoring tools.

/api/v1/system/health — no authentication required, HTTP 503 if any DOWN

{
"data": {
"status": "UP",
"uptime_ms": 1720008,
"components": {
"cassandra": "UP",
"redis": "UP",
"mqtt": "UP",
"node_red": "UP",
"opc_ua": "UP"
}
}
}

If even one component is DOWN, the response is status=DEGRADED + HTTP 503. The 90-second health probe in OTA upgrade.sh uses this to decide on auto-rollback.

Data / configuration locations

/data1/ # 컨테이너 ↔ host bind mount, 컨테이너 교체에도 보존
├── pp-data/
│ ├── cassandra/{data, hints} # SSTables, hints
│ ├── redis/ # AOF / RDB
│ ├── hivemq/ # MQTT persistence
│ └── node-userdir/ # Node-RED flows + node_modules
├── pp-temp/cassandra/commitlog # 휘발성 commit log
└── pp-backups/ # backup.sh 산출물 + OTA pre-snapshot

/etc/kopens/ # 설정 + signal files (read-write mount)
├── app.properties # 메인 설정 (165줄, 16개 섹션)
├── credentials.txt # 박스별 비번 (chmod 0600, 설치 시 1회 출력)
├── version.env # KOPENS_VERSION=<tag>
├── upgrade.status / upgrade.request # OTA 시그널
└── host-action.status / .request # restart/reboot/clean signal

/var/security/plantpulse/edge/ # SSL keystore (read-only mount, 100년 self-signed)

OTA upgrade

Automatic (latest from product.kopens.io)

sudo bash /opt/kopens/install/upgrade.sh

To a specific tag

sudo bash /opt/kopens/install/upgrade.sh --to 2026-20260601

Rollback to the previous tag

sudo bash /opt/kopens/install/upgrade.sh --rollback

Check only whether a new build exists

sudo bash /opt/kopens/install/upgrade.sh --check

Flow

1. META-INF/VERSION.JSON 의 build_date 비교 (--check 모드 / auto 모드)
2. pre-snapshot → /data1/pp-backups/pe-backup-<ts>.tar.zst
3. docker pull <new-tag>
4. /etc/kopens/version.env 갱신 + systemctl restart
5. /api/v1/system/health 90초 probe
6a. all UP → success — snapshot 경로 유지
6b. DEGRADED → auto-rollback to previous tag + snapshot 경로 안내

States: cat /etc/kopens/upgrade.statusidle | running | success | rolling-back | rolled-back | error.

UI / API trigger (from inside the container)

echo '{"target_tag":"2026-20260601"}' > /etc/kopens/upgrade.request

kopens-upgrade.path on the host (inotify) detects it → runs upgrade.sh --from-trigger.

Passwords (at mass-production shipment)

Since iter 9 (2026.05), install.sh automatically generates random passwords per box on first installation.

  • Location: /etc/kopens/credentials.txt (chmod 0600 root)
  • Contents: admin / mqtt / opcua / API key / keystore passwords
  • Shipping procedure: print/store → include when sealing the box → can be re-checked with cat (root only)

Changing them during operation:

config.sh --set edge.admin_password "NewStrongPass!"
config.sh --restart

The entrypoint automatically syncs HiveMQ auth.properties with the mqtt.* entries in /etc/kopens/app.properties on every boot, so only app.properties needs to be changed.

Resource limits (cgroup)

Defaults in the systemd unit:

keyvalue
MemoryMax12G
MemoryHigh11G
CPUQuota600% (6 cores)
TasksMax8192

Override for 8GB boxes (drop-in)

sudo mkdir -p /etc/systemd/system/plantpulse-edge.service.d
sudo tee /etc/systemd/system/plantpulse-edge.service.d/override.conf <<'EOF'
[Service]
Environment=HIVEMQ_HEAP=1g
Environment=CASSANDRA_HEAP=1g
Environment=TOMCAT_HEAP=1g
MemoryMax=6G
MemoryHigh=5G
EOF
sudo systemctl daemon-reload
sudo systemctl restart plantpulse-edge.service

Component heap defaults

  • HiveMQ: -Xms2g -Xmx2g (override with env HIVEMQ_HEAP — 2g is the 2026-07 heap standard)
  • Cassandra: auto-calculated from the host /proc/meminfo (1/4 of total) — 16G host → ~4G (env CASSANDRA_HEAP)
  • Tomcat: -Xms2g -Xmx2g (env TOMCAT_HEAP)
  • Redis / Node-RED: defaults

Logs

logrotate (cronie) inside the container handles everything automatically: daily / size>100M trigger / 14-day gzip retention / copytruncate (no application restart required).

ComponentPath (inside the container)tool
Tomcat app$PE_HOME/server/log/system.loglogs.sh tomcat
Tomcat stdout$PE_HOME/server/logs/catalina.outlogs.sh catalina
Cassandra$PE_HOME/db/logs/system.loglogs.sh cassandra
HiveMQ$PE_HOME/mqtt/logs/hivemq.loglogs.sh mqtt
Redis$PE_HOME/cache/log/redis.loglogs.sh redis
Node-RED$PE_HOME/node/log/node-red.loglogs.sh node-red
API audit$PE_HOME/server/log/api.loglogs.sh api
hostjournalctl -u plantpulse-edge.servicejournalctl

Troubleshooting (quick reference)

For the detailed scenario matrix, see /opt/kopens/install/RUNBOOK.md.

SymptomQuick fix
Some /health components DOWNTrace the cause with logs.sh <component>. If it is mqtt, verify that the passwords in auth.properties and app.properties match
Container restart loopCheck journalctl -u plantpulse-edge -n 100 and port occupancy (ss -tlnp | grep :80)
Docker card on /ui/apps is emptydocker.sock mount is missing — check -v /var/run/docker.sock in the systemd unit
PLC flappingCheck NET_RAW cap / PLC ports (MELSEC 5001, LS 2004, Modbus 502, OPC UA 49320)

If not recovered within 30 minutes → escalation

sudo bash /opt/kopens/install/bin/backup.sh # 1. 악화 전 스냅샷
sudo bash /opt/kopens/install/bin/doctor.sh # 2. 진단 tarball (≈200KB)
# 3. /tmp/pe-doctor-*.tar.zst + .sha256 을 support@kopens.io 또는 https://support.kopens.io 업로드

Contents of the pe-doctor tarball: api / docker / systemd / logs for the 7 components / config (passwords redacted) / host metrics.

  • Installation: 설치 > 한눈에 보기
  • Full REST API: 고급 / 통합 파트너용 > REST API
  • Host OS / sysctl / nmcli: /opt/kopens/install/install.sh and install/RUNBOOK.md on the box
  • Scenario matrix (A–E): /opt/kopens/install/RUNBOOK.md on the box