Serienfertigungslinie – Installation (factory.sh)
Wird verwendet, wenn in der Fertigungslinie 100 bis 1000 Boxen abgearbeitet werden. Der Bediener füllt nur einen Prompt-Bildschirm aus — EDGE_ID / Hostname / Zugangsdaten / Docker / cosign verify / Containerstart laufen automatisch. 30 Sekunden pro Box.
Bei einer einzelnen Box bzw. einer Vor-Ort-Installation (SI-Mitarbeiter) lesen Sie zuerst die Seite Schnellinstallation (Einzeiler). Serienfertigungslinie und Vor-Ort-Installation unterscheiden sich nur im Einstiegspunkt, das Ergebnis ist identisch.
0. Auf einen Blick
sudo -i
mkdir -p /home/kopens
curl -fsSL https://product.kopens.io/plantpulse-edge/plantpulse-edge-docker.tar.gz \
| tar xz -C /home/kopens
cd /home/kopens/plantpulse-edge-docker/bin
sudo bash factory.sh
factory.sh erledigt automatisch:
- Automatische Erkennung der LAN1-NIC-MAC — erzeugt
EDGE_<HEX6>aus den letzten 6 Stellen der MAC (z. B.EDGE_3F8A21). - Hostname-Abgleich — auch
hostnamewird aufedge-<hex6>(RFC 1123, Kleinbuchstaben + Bindestrich) geändert. - Prompt mit 5 Feldern — SITE_ID / SERVER_HOST / SERVER_API_KEY / LAN1 NIC / LAN2 NIC.
- Delegation an
install.sh— Docker / cosign / random secret / app.properties / Containerstart. - Ausgabe von factory-label.txt — zum Aufkleben auf die Box. Nach dem Druck versiegeln.
- Append an factory-inventory.csv — am Ende der Linie einsammeln → interne Inventory-DB.
1. Automatische Erzeugung von ID / Hostname
EDGE_ID — EDGE_<HEX6>
LAN1 NIC eth1 MAC = 00:1a:2b:3f:8a:21
─────
마지막 6 자 (HEX6) = 3F8A21
EDGE_ID = EDGE_3F8A21
hostname = edge-3f8a21
Why MAC?
- Der Hostname kann sich bei jeder OS-Installation ändern (cloud-init /
hostnamectl) und kollidieren - Die MAC ist fest in der Hardware hinterlegt und garantiert Eindeutigkeit pro Box
- Letzte 6 Stellen der 24 Bit → ca. 16,7 Mio. Kombinationen. Bei 1000 Boxen Serienfertigung liegt die Kollisionswahrscheinlichkeit bei ~0,003 % (nach Geburtstagsparadoxon sicher)
Die Domänenregeln (CLAUDE.md im Produkt-Repository) werden erzwungen:
| Bezeichner | Regex | Beispiel |
|---|---|---|
EDGE_ID | ^EDGE_[A-Z0-9_]{1,60}$ | EDGE_3F8A21 |
SITE_ID | ^SITE_[A-Z0-9_]{1,60}$ | SITE_FAB1_042 |
| hostname (RFC 1123) | Kleinbuchstaben + Bindestrich | edge-3f8a21 |
factory.sh fährt erst nach Prüfung der obigen Regex fort — schlägt die Prüfung fehl, wird sofort abgebrochen.
MAC-Kollision / Box ohne NIC
- Kollisionsmöglichkeit — existiert dieselbe EDGE_ID bereits in
/data1/factory-inventory.csv, wird sofort abgebrochen (verhindert stille Duplikate). Doppeltes Provisioning derselben Box oder MAC-Kollisionen werden automatisch erkannt. - Box ohne MAC (z. B. virtuelle NIC) —
derive_edge_id_from_macschlägt fehl → install.sh weicht auf einen Hostname-basierten Fallback aus. In der Linie tritt das praktisch nie auf.
2. Prompt mit 5 Feldern
Eingabe durch den Bediener in der Linie:
══════════════════════════════════════════════════════════════════════
PlantPulse Edge — Factory Provisioning
══════════════════════════════════════════════════════════════════════
Detected NIC eth1 MAC : 00:1a:2b:3f:8a:21
Auto EDGE_ID : EDGE_3F8A21
Auto hostname : edge-3f8a21
══════════════════════════════════════════════════════════════════════
Site ID (^SITE_[A-Z0-9_]+) [SITE_00001]: SITE_FAB1_042
Platform server host [192.168.0.41]: 10.10.0.5
Platform API key []: kFa7bGz8pQrN3xMv9wT2sLcEjY1uV6oH
LAN1 NIC (PLC) [eth1]: ← Enter = default
LAN2 NIC (WAN) [eth2]: ← Enter = default
══════════════════════════════════════════════════════════════════════
Summary
EDGE_ID : EDGE_3F8A21
hostname : edge-3f8a21
SITE_ID : SITE_FAB1_042
SERVER_HOST : 10.10.0.5
SERVER_API_KEY : kFa7…(32 chars)
LAN1 NIC (PLC) : eth1
LAN2 NIC (WAN) : eth2
══════════════════════════════════════════════════════════════════════
Proceed with install.sh? [y/N]
Nach Drücken von y läuft install.sh 5 bis 10 Minuten (inkl. erstem Image-Pull von 3 GB) und gibt anschließend das Label aus.
3. Automatisch erzeugte Zugangsdaten (G2)
install.sh erzeugt für jede Box ein anderes Zufallspasswort (Details im heruntergeladenen plantpulse-edge-docker/README.md, Abschnitt Secrets):
| Variable | Länge | Ablageort |
|---|---|---|
ADMIN_PASS (UI-Login) | 14 Zeichen zufällig +! | /etc/kopens/credentials.txt |
API_KEY (REST) | 16 Zeichen zufällig | Obige Datei + env.sh.generated |
MQTT_PASS (HiveMQ) | 14 Zeichen zufällig +! | Obige Datei |
OPCUA_PASS | 14 Zeichen zufällig +! | Obige Datei |
CERT_PASS (SSL keystore) | 14 Zeichen zufällig +! | Obige Datei |
/etc/kopens/env.sh.generated (chmod 0600 root) ist das Sidecar, das alle nachfolgenden Skripte (upgrade.sh / restart.sh) sourcen — die Zugangsdaten bleiben auch nach einem Neustart identisch.
4. Verifikation der Image-Signatur (G3)
install.sh installiert cosign automatisch, legt cosign.pub ab und verifiziert unmittelbar nach dem docker pull automatisch.
[install] Installing cosign ...
[install] OK — cosign installed (cosign version 2.4.1)
[install] cosign.pub installed — image verification enabled
[install] docker pull — docker.kopens.io/pe/plantpulse-edge:2026-20260523
[install] OK — Pull complete
[cosign] OK — signature verified for docker.kopens.io/pe/plantpulse-edge:2026-20260523
Ist cosign.pub noch ein Platzhalter (das Betriebsteam hat noch kein Keypair erzeugt), erfolgt nur eine WARN-Meldung, die Installation läuft weiter.
Siehe den Abschnitt Cosign im heruntergeladenen plantpulse-edge-docker/README.md.
5. Label + Inventar
/etc/kopens/factory-label.txt — zum Aufkleben auf die Box
Nach Abschluss der Installation erfolgt die Ausgabe am Bildschirm sowie die Speicherung in der Datei chmod 0600. Der Linienmitarbeiter druckt das Label auf dem Etikettendrucker und versiegelt die Box:
══════════════════════════════════════════════════════════════════════
PlantPulse Edge — Factory Label
══════════════════════════════════════════════════════════════════════
EDGE_ID : EDGE_3F8A21
hostname : edge-3f8a21
SITE_ID : SITE_FAB1_042
build_date : 2026-05-19 14:25:33
──────────────────────────────────────────────────────────────────────
LAN1 (PLC) : eth1 MAC=00:1a:2b:3f:8a:21
LAN2 (WAN) : eth2 MAC=00:1a:2b:3f:8a:22
──────────────────────────────────────────────────────────────────────
UI admin : admin / aBcD1234EfGh!
REST API : kFa7bGz8pQrN3xMv9wT2sLcEjY1uV6oH
(full credentials → /etc/kopens/credentials.txt — root only)
══════════════════════════════════════════════════════════════════════
/data1/factory-inventory.csv — zum Einsammeln in der Linie
Pro Box wird eine Zeile angehängt. Am Ende der Linie sammelt der Bediener sie ein → Upload in die interne Inventory-DB:
edge_id,hostname,site_id,server_host,lan1_iface,lan1_mac,lan2_iface,lan2_mac,build_date,iso8601
EDGE_3F8A21,edge-3f8a21,SITE_FAB1_042,10.10.0.5,eth1,00:1a:2b:3f:8a:21,eth2,00:1a:2b:3f:8a:22,2026-05-19 14:25:33,2026-05-19T05:25:33Z
EDGE_5B7C03,edge-5b7c03,SITE_FAB1_043,10.10.0.5,eth1,00:1a:2b:5b:7c:03,eth2,00:1a:2b:5b:7c:04,2026-05-19 14:28:12,2026-05-19T05:28:12Z
6. Sammelerfassung am Linienende
# 라인 마지막 박스 처리 후 회수 워크스테이션에서
scp root@edge-3f8a21:/data1/factory-inventory.csv ./inventory-line1-$(date +%F).csv
# 회수한 CSV 들을 사내 inventory DB 로 업로드 (예: scripts/import-inventory.py)
python3 import-inventory.py inventory-line1-2026-05-19.csv
Alternativ kann ein Hook ergänzt werden, der beim Einschalten der Box automatisch an die Platform pusht (Phase 1 — bei Einführung der internen Provisioning-REST API).
7. Häufige Stolperfallen
| Symptom | Ursache | Maßnahme |
|---|---|---|
EDGE_ID '...' fails ^EDGE_[A-Z0-9_]{1,60}$ | Die MAC der LAN1-NIC ist eine virtuelle NIC ohne ASCII-Wert | Explizit angeben, z. B. LAN1_IFACE=enp1s0 bash factory.sh |
already_in_inventory: EDGE_3F8A21 already provisioned | Erneuter Lauf derselben Box oder MAC-Kollision | Betreffende Zeile mit vi /data1/factory-inventory.csv entfernen und erneut ausführen. Bei MAC-Kollision Linie stoppen + melden |
cosign verify FAILED (COSIGN_REQUIRE=1) | Image unsigniert ODER falsche cosign.pub | Prüfen, ob der Aufruf von sign-image.sh auf dem Build-Server fehlt; cosign.pub aktualisieren |
hostnamectl set-hostname failed | Ausführung innerhalb eines Containers / fehlende Rechte | factory.sh erzwingt root — sudo bash factory.sh |
| Prompt nicht sichtbar (Label wird nicht gedruckt) | install.sh ist mittendrin fehlgeschlagen | journalctl -u plantpulse-edge.service -n 50 prüfen, dann Troubleshooting |
8. Verwandte Dokumente
plantpulse-edge-docker/README.md— Abschnitt Betriebsszenarien (Serienfertigung / SI / CI), im Paket enthaltenplantpulse-edge-docker/README.md— Abschnitt Cosign (Keypair-Erzeugung · Rollout · Rotation)- Schnellinstallation (Einzelbox, für SI vor Ort)
- Checkliste direkt nach der Installation
- Air-Gap-Netzwerk- / Airgap-Installation