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.
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/healthresponse + HTTP code - Upgrade status: contents of
/etc/kopens/upgrade.status(idle/running/success/...)
Day-to-day operations commands
| Task | Command |
|---|---|
| Check status | bash /opt/kopens/install/bin/status.sh |
| Health (exit-code based) | bash /opt/kopens/install/bin/health.sh |
| View logs | bash /opt/kopens/install/bin/logs.sh tomcat (or cassandra/mqtt/redis/node-red/api/catalina) |
| Follow logs | bash /opt/kopens/install/bin/logs.sh -f tomcat |
| Shell inside the container | bash /opt/kopens/install/bin/shell.sh |
| Change settings | bash /opt/kopens/install/bin/config.sh --set <key> <value> |
| Restart | sudo systemctl restart plantpulse-edge.service |
| Backup | sudo bash /opt/kopens/install/bin/backup.sh |
| Restore | sudo bash /opt/kopens/install/bin/restore.sh <archive> |
| Collect diagnostics (escalation) | sudo bash /opt/kopens/install/bin/doctor.sh |
| OTA upgrade | sudo 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.status — idle | 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:
| key | value |
|---|---|
| MemoryMax | 12G |
| MemoryHigh | 11G |
| CPUQuota | 600% (6 cores) |
| TasksMax | 8192 |
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 envHIVEMQ_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(envTOMCAT_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).
| Component | Path (inside the container) | tool |
|---|---|---|
| Tomcat app | $PE_HOME/server/log/system.log | logs.sh tomcat |
| Tomcat stdout | $PE_HOME/server/logs/catalina.out | logs.sh catalina |
| Cassandra | $PE_HOME/db/logs/system.log | logs.sh cassandra |
| HiveMQ | $PE_HOME/mqtt/logs/hivemq.log | logs.sh mqtt |
| Redis | $PE_HOME/cache/log/redis.log | logs.sh redis |
| Node-RED | $PE_HOME/node/log/node-red.log | logs.sh node-red |
| API audit | $PE_HOME/server/log/api.log | logs.sh api |
| host | journalctl -u plantpulse-edge.service | journalctl |
Troubleshooting (quick reference)
For the detailed scenario matrix, see /opt/kopens/install/RUNBOOK.md.
| Symptom | Quick fix |
|---|---|
| Some /health components DOWN | Trace the cause with logs.sh <component>. If it is mqtt, verify that the passwords in auth.properties and app.properties match |
| Container restart loop | Check journalctl -u plantpulse-edge -n 100 and port occupancy (ss -tlnp | grep :80) |
| Docker card on /ui/apps is empty | docker.sock mount is missing — check -v /var/run/docker.sock in the systemd unit |
| PLC flapping | Check 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.
References / related pages
- Installation:
설치 > 한눈에 보기 - Full REST API:
고급 / 통합 파트너용 > REST API - Host OS / sysctl / nmcli:
/opt/kopens/install/install.shandinstall/RUNBOOK.mdon the box - Scenario matrix (A–E):
/opt/kopens/install/RUNBOOK.mdon the box