Container Mode Operation
Starting from the 2026.05 release, PlantPulse Edge is deployed as a single Docker container. This page is a comprehensive guide for the daily operation and troubleshooting of the container mode.
For boxes using the existing native deployment (installed directly on the system), please continue to use the native pages such as 시작 (start.sh), 중지 (stop.sh), and 재시작 (restart.sh) in the left menu. This page is exclusively for container deployments (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: 9 ports (80, 443, 1883, 1884, 6379, 9042, 1880, 12000, 12443). 7799 (Tomcat JMX) is not listed as it is exclusive to 127.0.0.1.
- App.properties core keys (edge.id / site_id / dev.mode / mqtt.enable / sparkplug.enable)
- API:
/api/v1/system/version+/api/v1/system/healthresponse + HTTP code - Upgrade status:
/etc/kopens/upgrade.statuscontent (idle/trial/committed/...)
Daily operation commands
| Task | Command |
|---|---|
| Check status | bash /opt/kopens/install/bin/status.sh |
| Health check (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 |
| Container internal shell | bash /opt/kopens/install/bin/shell.sh |
| Change configuration | 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 |
| Recovery | sudo bash /opt/kopens/install/bin/restore.sh <archive> |
| Diagnosis collection (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 use: 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 any component is DOWN, returns status=DEGRADED + HTTP 503. For OTA upgrade.sh, the trial run is determined via a separate judgment address /api/health?verdict=upgrade&expect_build=<빌드일> (default 300 seconds).
Data / Configuration location
/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
By specific tag
sudo bash /opt/kopens/install/upgrade.sh --to 2026.11-20261103-1006
Only immutable tags (YYYY.MM-YYYYMMDD-HHMM) are accepted.
Rollback of upgrade in progress
sudo bash /opt/kopens/install/upgrade.sh --rollback
Works only in trial · rollback_failed states. It does not allow downgrading from a committed build to an older build.
Check for existence of new build only
sudo bash /opt/kopens/install/upgrade.sh --check
Flow
The sequence is identical to the «Execution Order» in Upgrade. Pre-inspection → Download → Signature verification → Snapshot → Transition → Trial run → Commit or automatic rollback.
States: cat /etc/kopens/upgrade.status — idle · downloading · verified · snapshot · switching · trial · committed · rolling_back · rolled_back · rollback_failed.
UI / API trigger (inside container)
POST /api/v1/system/upgrade uses /etc/kopens/upgrade.request.
Host kopens-upgrade.path (inotify) detects → upgrade.sh --from-trigger executes.
Passwords (at mass production shipment)
From iter 9 (2026.05) onwards, random passwords are automatically generated for each box during the first install.sh execution.
- Location:
/etc/kopens/credentials.txt(chmod 0600 root) - Content: admin / mqtt / opcua / API key / keystore passwords
- Shipment procedure: Print/save → include when sealing the box → can be re-verified using cat (root only)
Changing during operation:
config.sh --set edge.admin_password "NewStrongPass!"
config.sh --restart
Since HiveMQ auth.properties automatically syncs with mqtt.* in /etc/kopens/app.properties at every boot via the entrypoint, only app.properties needs to be changed.
Resource limits (cgroup)
systemd unit defaults:
| 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 via envHIVEMQ_HEAP— 2026-07 heap standard 2g) - Cassandra : auto-calc based on host /proc/meminfo (1/4 of total) — 16G host → ~4G (env
CASSANDRA_HEAP) - Tomcat :
-Xms2g -Xmx2g(envTOMCAT_HEAP) - Redis / Node-RED : Default
Logs
logrotate (cronie) inside the container automatically handles daily / size>100M triggers / 14-day gzip retention / copytruncate (without app restart).
| Component | Path (inside 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 (Brief)
For installation scenarios (mass production line · single box site · CI), refer to Installation.
| Symptom | Quick Fix |
|---|---|
| Some /health components DOWN | Trace cause with logs.sh <component>. For mqtt, verify password match between auth.properties / app.properties |
| Container restart loop | Check journalctl -u plantpulse-edge -n 100 + port occupancy (ss -tlnp | grep :80) |
| /ui/apps docker card is empty | Missing docker.sock mount — check -v /var/run/docker.sock in systemd unit |
| PLC blinking | Check NET_RAW cap / PLC port (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 업로드
pe-doctor tarball contents: api / docker / systemd / 7-component logs / config (passwords redacted) / host metrics.
References / Related Pages
- Installation:
설치 > 한눈에 보기 - Full REST API:
고급 / 통합 파트너용 > REST API - Host OS / sysctl / nmcli: Box
/opt/kopens/install/install.sh - Installation Scenarios: Installation