Upgrade
Container Mode (2026.05+, Recommended)
# 자동 (META-INF/VERSION.JSON 이 가리키는 빌드)
sudo bash /opt/kopens/install/upgrade.sh
# 특정 불변 태그 (YYYY.MM-YYYYMMDD-HHMM). 움직이는 태그는 거부합니다
sudo bash /opt/kopens/install/upgrade.sh --to 2026.11-20261103-1006
# 진행 중인 현재 업그레이드만 롤백 (trial · rollback_failed 상태에서만)
sudo bash /opt/kopens/install/upgrade.sh --rollback
# 사전 점검만 (0 최신, 10 새 빌드 있음)
sudo bash /opt/kopens/install/upgrade.sh --check
--rollback only reverts an ongoing upgrade; it does not downgrade a finalized build to an older build. It will be rejected even if an older tag is provided via --to (Exit Code 3).
Boxes that cannot reach the registry are upgraded using a single image file — see Air-gapped Upgrade below.
Execution Sequence (Automatic):
- Pre-inspection — Checks if the target is an immutable tag, if it is newer than the current build, and if the signing tool, backup tool, and sufficient disk space are available. If any condition is not met, the process stops without making any changes.
- Download —
docker pull <태그> - Verification — Verifies the cosign signature and the
build_dateof the image. If the signature cannot be verified, the process does not proceed. The process continues by replacing itself with the upgrade tool contained in the verified image. - Snapshot —
/data1/pp-backups/pe-backup-pre-upgrade-<ts>.tar.zstbackup, followed by CQL dump (<아카이브>.cql/, below) and Cassandra snapshot. This is mandatory and cannot be skipped. If any of these fail, the process stops without making any changes (snapshot_failed, Exit Code 4). - Transition — Replaces
/etc/kopens/version.envwith the verified digest and restarts. - Trial Run — Waits until
/api/health?verdict=upgrade&expect_build=<빌드일>returns 200. The default timeout is 300 seconds (HEALTH_TIMEOUT), and up to 2400 seconds (MIGRATION_TIMEOUT) if migration is in progress. - Finalization or Automatic Rollback — If successful,
committed. If it fails, Cassandra is reverted to the snapshot and the system returns to the previous image (rolled_back). If this recovery also fails,rollback_failed.
If power is lost during the trial run, kopens-upgrade-resume.service re-evaluates as --resume upon booting. If booting occurs more than 3 times without finalization (OTA_MAX_TRIAL_BOOTS), it rolls back without evaluation.
Progress Status: cat /etc/kopens/upgrade.status — JSON. Statuses are idle · downloading · verified · snapshot · switching · trial · committed · rolling_back · rolled_back · rollback_failed.
Exit Codes: 0 Finalized or already up-to-date · 10 --check New build available · 3 Downgrade request rejected · 4 No changes made · 5 Download or verification failure · 6 Rollback complete · 7 Rollback failed · 75 Another upgrade in progress.
UI / API Trigger: POST /api/v1/system/upgrade uses /etc/kopens/upgrade.request, which is detected by kopens-upgrade.path on the host to execute upgrade.sh --from-trigger.
Detailed Guide: "OTA Upgrade" section of Container Mode Operations.
CQL Dump Before Upgrade
Beyond tar archives and Cassandra snapshots, a copy independent of the engine is created for preliminary backup — the schema as CQL text (schema.cql) and rows as CSV for each table. This is because there is no guarantee that engine files from one version will be readable by a new engine in an upgrade where the DB engine changes.
- Location:
<아카이브에서 .tar.zst 를 뗀 이름>.cql/next to the archive. Only the three most recent dumps are kept alongside the archives. - Rows of time series and monitoring tables are not included (only schemas are kept, and they return empty). The exclusion list is
BACKUP_CQL_EXCLUDE_TABLES. - Failure to create a dump results in backup failure, and the upgrade will not start. If you must proceed without a dump, specify
BACKUP_CQL=0— a warning will be logged, and that archive can only be restored on the same engine.
Restoration is detailed in pe restore --cql of Backup and Recovery.
Air-gapped Upgrade
Follows the same upgrade procedure (Pre-inspection → Snapshot → Transition → Trial Run → Finalization or Rollback) using an image file without a registry or internet connection.
sudo pe upgrade --bundle /media/usb/plantpulse-edge-2026.12.tar.zst
# 박스에 cosign 3 이 없으면 바이너리를 같이 넘깁니다
sudo pe upgrade --bundle <파일> --cosign /media/usb/cosign-linux-amd64
- Three files must be in the same location:
<파일>,<파일>.sha256, and<파일>.sha256.sig. Use those within the air-gapped bundle'simages/or from the distribution site'splantpulse-edge-<YYYY.MM>.tar.zst. - Verify the signature first. Use
/etc/kopens/cosign.pubon the box to perform an offline verification of the signature of.sha256; only when the sha256 of the file matches the signed value does it proceed todocker load. If the signature file is missing, the signature is incorrect, or the sha256 differs, the image is not loaded (independent ofCOSIGN_REQUIRE). - cosign: If cosign 3 is not on the box, install
--cosign <파일>, orcosign-linux-<arch>next to the file, ortools/cosign-linux-amd64from the bundle. It will be rejected if the checksum differs from the fixed version (3.1.3). - Only newer builds can be installed. If it is the same build,
up_to_date; if it is an older build,refused_downgrade. --bundlecannot be used with--to·--check(Exit Code 2). The "SW Upgrade" button on the web uses only the registry path.
The upgrade.sh installed on releases without this feature does not know --bundle. For the first time, execute directly using the new script contained in the bundle.
sudo bash <번들>/repo/bin/upgrade.sh --bundle <번들>/images/<파일>
If only the image file was provided, bring the repository tarball (plantpulse-edge-docker.tar.gz and .sig) as well, extract it, and execute in the same manner. After that, it will work via pe upgrade --bundle.
Pre-release Rollback Validation
Before a new release is announced to field boxes, it is verified on a staging box that an intentionally failed upgrade actually rolls back. An upgrade is performed using a test image that fails migration to trigger an automatic rollback, and it is verified that the previous build, schema, and data remain intact. This test is a mandatory step in the release chain; only after passing is VERSION.JSON issued, and the box then recognizes that release as "latest". Health failure and boot-loop scenarios are run together in the release where the upgrade tool has changed.
2. Pre-inspection
Before starting the upgrade:
# 1. 외부 망이 충분히 빠른지 — 회선이 느리면 download 만 수십 분
$PE_HOME/bin/network-speed-test.sh
# 2. 디스크 여유 (산출물 크기의 2–3배는 있어야)
df -h /opt /data1
# 3. 살아있는 백업이 있는지
ls -lt /data1/pp-backup | head -3
3. Upgrade Result Verification
$PE_HOME/bin/ps.sh # 모든 컴포넌트 살아있는지
curl -s http://127.0.0.1/api/v1/edge | jq # 버전/엣지 ID 새 값 확인
curl -s http://127.0.0.1/ui/opcua/tree | jq '.data.tree | length' # 사이트/태그 정상
$PE_HOME/bin/log-viewer.sh # 30초 정도 봐서 SEVERE 없는지
# (Ctrl+C)
Also verify normal arrival at the external SCADA / Sparkplug receiving end.
4. Common Pitfalls
| Symptom | Cause / Resolution |
|---|---|
Stops at download install.sh | Check external network / product.kopens.io. Verify directly with curl -v http://product.kopens.io/... |
New output is corrupted after extracting | Interruption during download. Check disk space + retry |
| Only some components are active after upgrade | Step-by-step failure of start.sh — check log-viewer.sh to see where it is stuck |
cosign 3 or later is not installed and could not be installed (Exit Code 4) | Box cannot reach github.com to download cosign. Nothing is changed. Open the network or pre-install cosign 3.x and retry |
| Rollback to older version after upgrade | Restore from backup → Backup / Recovery |
5. firmware.sh — OS Package Update
$PE_HOME/bin/firmware.sh
Internally:
dnf update -y
dnf clean all
Used when applying security patches on a quarterly basis. If a kernel update is included, a reboot is required.
$PE_HOME/bin/firmware.sh
needs-restarting -r # 새 커널이 깔렸는지 확인
# 결과가 "Reboot is required" 이면
$PE_HOME/bin/stop.sh
$PE_HOME/bin/reboot.sh
Learn More
- Integrated Upgrade Scenarios (Safe Procedures) → Operating Scenarios — New Version Deployment
- Artifacts are created by the GitLab release chain (
edge:libs→edge:deploy-dev→edge:image→edge:sign→edge:staging→verify:staging-evidence→verify:ota-rollback:image→verify:ota-rollback→edge:version). - Installation / Deployment (For Developers): Installation / Deployment