Skip to main content

Air-Gapped Installation

This section describes the installation procedure for a server on an air-gapped network (with no internet access) that is blocked from the internet. The process consists of three stages.

① 인터넷 되는 PC ② USB 등 이동 매체 ③ 폐쇄망 서버
번들 내려받기 → 반출 → 로드 → 설정 → 기동
무결성·서명 검증 (검증 자동 재확인)

The server specifications, ports, and firewall requirements are the same as those in the "Prerequisites" section of the Installation document. Please review that section first.


0. Preparing the Air-Gapped Server​

The one-line installation script downloads Docker from the internet if it is not present — this path will not work in an air-gapped network. Please ensure Docker is installed beforehand.

docker --version
docker compose version # v2.22 이상

You can install it from the distribution's offline repository or using RPM/DEB packages. If you want to also perform signature verification, please bring in the cosign binary as well (optional — if it's not present, only the verification step will be skipped).


1. Downloading on an Internet-Connected Machine​

There are four files to download.

FileDescription
plantpulse-studio-images-<version>.tar.gzBundle of 5 container images (approx. 2.8 GB)
…tar.gz.sha256Checksum for integrity verification
…tar.gz.sigCosign signature for origin (signature) verification
plantpulse-studio-docker.tar.gzOperational package — bin/ script · compose · .env.example · cosign.pub
BASE=https://product.kopens.io/plantpulse-studio
VER=2026.08 # 또는: VER=$(curl -fsSL $BASE/latest.txt)

# 번들은 수 GB — 전송이 끊기면 -C - 가 이어받습니다
curl -fLO -C - --retry 5 $BASE/plantpulse-studio-images-$VER.tar.gz
curl -fLO $BASE/plantpulse-studio-images-$VER.tar.gz.sha256
curl -fLO $BASE/plantpulse-studio-images-$VER.tar.gz.sig
curl -fLO $BASE/plantpulse-studio-docker.tar.gz
Choosing a Version — latest.txt

latest.txt is a one-line file containing only the name of the latest version (e.g., 2026.08). It is not a copy of the bundle, so the file you download will not change even if a new version is released.

Once a version is published, it is never deleted. Even if 2026.09 is released, plantpulse-studio-images-2026.08.tar.gz remains available, so you can always use that address to re-download a version you were using or to roll back. If you have scripted your installation procedure, it is safer to specify the version directly instead of using latest.txt.

What is Included in the Image Bundle

It contains six images — Studio server · web · session runtime · builder sidecar · Docker socket proxy, and PostgreSQL. There are no additional images you need to download for an air-gapped network.

The stack itself does not launch a PostgreSQL container (it uses an external PG). Since there may not be a suitable PG available in an air-gapped network, the image is included in the bundle so you can set up PG on-site if needed.

Integrity and Origin Verification (Before Transfer)​

First, extract the operational package to retrieve the public key (cosign.pub).

mkdir -p pkg && tar xzf plantpulse-studio-docker.tar.gz -C pkg --strip-components=1

# ① 무결성 — 전송 중 파일이 깨지지 않았는가
sha256sum -c plantpulse-studio-images-$VER.tar.gz.sha256

# ② 출처 — KOPENS 가 서명한 번들이 맞는가
cosign verify-blob --key pkg/cosign.pub --insecure-ignore-tlog=true \
--signature plantpulse-studio-images-$VER.tar.gz.sig \
plantpulse-studio-images-$VER.tar.gz
Why --insecure-ignore-tlog is needed

Per company registry policy, we do not use a public transparency log (Rekor). This option only skips the querying of the public log; the signature itself is still cryptographically verified.

If the Downloaded File Looks Like an Old Version

It might be a CDN cache. Append ?v=$(date +%s) to the URL and download it again.


2. Transferring via Removable Media​

Copy the four files below as-is to a USB drive, etc. Do not forget .sha256 and .sig — the import-side script will automatically re-verify using these files.

plantpulse-studio-images-2026.08.tar.gz
plantpulse-studio-images-2026.08.tar.gz.sha256
plantpulse-studio-images-2026.08.tar.gz.sig
plantpulse-studio-docker.tar.gz

3. Importing on the Air-Gapped Server​

3-1. Deploying the Operational Package​

sudo mkdir -p /opt/kopens/plantpulse-studio-docker
sudo tar xzf /media/usb/plantpulse-studio-docker.tar.gz \
-C /opt/kopens/plantpulse-studio-docker --strip-components=1

cd /opt/kopens/plantpulse-studio-docker
mkdir -p dist
sudo cp /media/usb/plantpulse-studio-images-2026.08.tar.gz* dist/

3-2. Loading Images​

sudo bash bin/load.sh dist/plantpulse-studio-images-2026.08.tar.gz

If load.sh is in the same folder as .sha256 and .sig, it will automatically verify them, and stop the import if they don't match.

✅ 서명 검증 통과
▶ 로드 중: dist/plantpulse-studio-images-2026.08.tar.gz
✅ 로드 완료 — cp .env.example .env 설정 후 bin/up.sh
If You See a Verification Skipped Warning

If you see ⚠ 서명 검증 생략(.sig/cosign.pub/cosign 중 부재), it means one of the three is missing. Please decide whether to proceed without verification according to your security policy — at the very least, it is recommended to pass the .sha256 integrity check.

3-3. Creating the Configuration File​

cp .env.example .env
vi .env
chmod 600 .env

These are the items that must be adjusted for an air-gapped network.

ItemValueReason
REGISTRYLeave empty (REGISTRY=)If a value is set, it will attempt a registry pull on every startup, causing delays and warnings
PP_IMAGE_TAGVersion of the imported bundle (2026.07)Must match the loaded image tag
DATABASE_URLpostgres://ppstudio:<password>@<호스트>:5432/ppstudioExternal PG connection — the password is embedded in this URL
PLATFORM_API_TARGETOn-site platform addressTarget for real data and authentication delegation
STUDIO_LOCAL_USERSadmin:<password>First login account
PP_LANG / PP_TZko / Asia/SeoulKorean on-site

For AI and platform keys, refer to Secret Management and enter them in .env . The DB and roles must be created beforehand — follow the "Database Preparation" section of Installation and bin/provision-platform-db.sh exactly.

3-4. Startup​

bash bin/up.sh
ℹ️ REGISTRY 비어있음(로컬/에어갭) — pull 생략, 로컬 이미지 사용
⏳ 헬스 대기...
✅ PlantPulse Studio 시작됨 → http://192.168.x.x/

4. Installation Verification​

bash bin/status.sh
bash bin/smoke-install.sh

smoke-install.sh checks the health, web response, actual login, session runtime image, and container status all at once. If all of them pass, the system is actually usable.

Access http://<server-ip>/ from a browser and log in with the STUDIO_LOCAL_USERS account. The subsequent steps are the same as the "First Login" section of the Installation document.


5. Updating an Air-Gapped Environment​

You can bring in a new version bundle using the same method, load it, and then restart.

cd /opt/kopens/plantpulse-studio-docker

bash bin/backup.sh # ① 먼저 백업
sudo cp /media/usb/plantpulse-studio-images-2026.08.tar.gz* dist/
sudo bash bin/load.sh dist/plantpulse-studio-images-2026.08.tar.gz # ② 새 이미지 로드
sed -i 's/^TAG=.*/TAG=2026.08/' .env # ③ 태그 변경
bash bin/restart.sh # ④ 재기동

To also update the operational script (bin/), extract the new plantpulse-studio-docker.tar.gz into a temporary folder and overwrite files, excluding .env and dist/ .

Never Overwrite .env and dist/

.env contains the platform address, account, and API keys, and dist/ contains local backups. Overwriting them entirely will prevent the stack from starting or will result in loss of backups.


6. Backup and Restore in an Air-Gapped Network​

The backup and restore scripts operate without internet access — this is because the postgres:18-alpine image required when using an external PostgreSQL is included in the import bundle.

bash bin/backup.sh # 백업
DRYRUN=1 bash bin/restore.sh # 복구 리허설(비파괴)

For more information, see Backup and Restore.


Next Steps​