You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
12 KiB
127 lines
12 KiB
|
1 month ago
|
# Web Configurator — `deploy/` 통합 가이드 (협력사 전달용)
|
||
|
|
|
||
|
|
> **목적**: `deploy/` 폴더의 구성요소 중 **꼭 필요한 것**과 그 **기능**을 정리하고, 기존 `dpworldapp`/펌웨어와의 **"충돌" 오해**를 해소합니다.
|
||
|
|
> **대상 버전**: v1.12.1 · **검증**: `deploy/` 통합 의미론은 v1.11.15 기준 소스 코드 + 실디바이스(192.168.55.54, 펌웨어 원본 상태) 대조 완료. v1.12.0 설치 경로 이전(`/usr/lib`)과 v1.12.1 `nginx.conf` 제거를 반영했습니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 0. 한눈에 — 핵심 3가지
|
||
|
|
|
||
|
|
1. **웹 설정기 앱 자체는 네트워크/AP 파일 없이도 단독으로 동작합니다** (`:9090`). 앱은 `src/`(파이썬) + `web-configurator.service` 두 가지만 있으면 기동·설정 저장이 됩니다.
|
||
|
|
2. **"충돌"의 실체는 단 3개 파일**(네트워크 드롭인)이 *펌웨어가 소유한 유닛을 덮어쓰는 것*뿐입니다. 그 외 모든 파일은 **새로 추가(additive)**되는 것이라 기존 자원을 전혀 건드리지 않습니다 — 크래시·에러를 내지 않습니다.
|
||
|
|
3. 따라서 **원하는 기능만 골라 설치**하면 충돌 없이 통합됩니다. (§3에 3가지 통합 방식)
|
||
|
|
|
||
|
|
> **경로 표준 (v1.12.0~, 협력사 협의 반영)**: 앱 코드는 **`/usr/lib/web-configurator`** 에 설치합니다 — FHS상 `/usr/lib` 가 read-only program code 자리이며, BSP가 이미지에 굽는 read-only rootfs에 적합합니다. 쓰기 런타임 데이터(로그·펌웨어 staging/upload·설정 백업)는 `/usr/lib`(read-only)가 아니라 **쓰기 가능한 영속 파티션(`/opt`, `/home/root`)** 에 둡니다(§4).
|
||
|
|
>
|
||
|
|
> **신규 텔레메트리 Uplink (v1.12.1)** 는 런타임에 OS 호스트 라우트(/32)만 조작하므로 **`deploy/` 추가 구성요소가 필요 없습니다** — 새 유닛/스크립트 없이 기존 `web-configurator.service`(root 권한) 만으로 동작합니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. 기능 그룹과 필요한 파일
|
||
|
|
|
||
|
|
`deploy/`의 구성요소는 **3개 기능 그룹**으로 나뉩니다. 그룹 단위로 켜고 끌 수 있습니다.
|
||
|
|
|
||
|
|
### A. 웹 설정기 (필수 — 항상 설치)
|
||
|
|
|
||
|
|
| 파일 | 기능 | 설치 위치 |
|
||
|
|
|---|---|---|
|
||
|
|
| (앱 본체 `src/`) | 파이썬 stdlib HTTP 서버. 웹 UI + 설정 API. `:9090` 리슨 | `/usr/lib/web-configurator/src` *(표준 — read-only rootfs 가능; 쓰기 데이터는 §4)* |
|
||
|
|
| `web-configurator.service` | 위 앱을 부팅 자동기동 + 크래시 시 재시작하는 systemd 유닛 | `${systemd_system_unitdir}` |
|
||
|
|
|
||
|
|
이 그룹만으로 웹 설정기가 동작합니다(설정은 DB `/home/root/db`에 저장). **`dpworldapp`과 충돌하지 않습니다.**
|
||
|
|
|
||
|
|
### B. 네트워크 즉시(라이브) 적용 — 선택
|
||
|
|
|
||
|
|
> **왜 필요한가**: `dpworldapp`은 **재기동 시에만** 네트워크/설정을 OS에 반영합니다. 이 그룹은 웹 UI에서 IP·Wi-Fi(SSID/비밀번호)를 바꾸면 **재부팅·dpworldapp 재기동 없이 즉시** 반영하기 위한 **보완** 구성입니다.
|
||
|
|
>
|
||
|
|
> **동작 메커니즘**: 웹이 렌더 파일을 `/home/root/network/`에 기록 → 적용 스크립트가 그것을 `/run/systemd/network/`로 동기화 + `networkctl`/`wpa_cli` 재구성. (※ `networkctl`은 `/home/root/network`를 직접 읽지 않으므로 이 **동기화 스크립트가 있어야** 라이브 적용이 됩니다.)
|
||
|
|
|
||
|
|
| 파일 | 기능 | 설치 위치 |
|
||
|
|
|---|---|---|
|
||
|
|
| `dpworld-network-apply-hardened.sh` | 네트워크 적용 스크립트. **펌웨어 원본의 안전 버전** — Wi-Fi country 변경 시 `modprobe -r wlan`(QCA6490 워치독 리부팅 루프 유발)을 제거하고 country를 **재부팅 시 적용(reboot-deferred)**으로 처리 | `/usr/bin/` (0755) |
|
||
|
|
| `dpworld-net-recover.service` *(옵션)* | wlan 모듈이 완전히 내려갔을 때 복구(`modprobe` + `wpa` 재시작). 웹/워치독이 on-demand로 호출 | `${systemd_system_unitdir}` |
|
||
|
|
|
||
|
|
> 위 스크립트를 **어떻게** 펌웨어 적용 경로에 연결할지(드롭인 vs 전용 유닛 vs 미사용)는 **§3**에서 선택합니다. 드롭인 3종은 §3 옵션 ③에서만 사용합니다.
|
||
|
|
|
||
|
|
### C. Wi-Fi AP 모드 — 선택
|
||
|
|
|
||
|
|
> **기능**: 장치를 Wi-Fi AP로 띄워 작업자가 휴대폰/노트북으로 직접 접속(현장 provisioning). `wlan0`(STA)은 건드리지 않고 **`ap0` 가상 인터페이스**를 추가해 사용. hostapd + udhcpd + **ap0 전용 방화벽**(INPUT 전체 개방·WPA2 PSK가 접근 게이트 / FORWARD 차단 = AP 클라이언트의 내부망·PLC(eth1) 경유 차단).
|
||
|
|
|
||
|
|
| 파일 | 기능 | 설치 위치 |
|
||
|
|
|---|---|---|
|
||
|
|
| `dpworld-ap-apply.sh` | AP 기동/해제 스크립트(ap0 생성·IP·방화벽·hostapd/udhcpd 시작) | `/usr/bin/` (0755) |
|
||
|
|
| `dpworld-ap-apply.service` | 웹이 on-demand로 호출하는 AP 적용 유닛 (`[Install]` 없음 = 부팅 자동기동 안 함) | `${systemd_system_unitdir}` |
|
||
|
|
| `dpworld-hostapd-ap0.service` | `ap0`에서 hostapd 실행 (`[Install]` 없음, ap-apply.sh가 기동) | `${systemd_system_unitdir}` |
|
||
|
|
| `dpworld-udhcpd-ap0.service` | `ap0`에서 DHCP 서버 실행 (`[Install]` 없음, ap-apply.sh가 기동) | `${systemd_system_unitdir}` |
|
||
|
|
| `dpworld-ap-seed.service` *(옵션)* | 재부팅 후 AP를 자동 재기동(복구). **없으면 재부팅 후 AP 수동 재활성 필요** | `${systemd_system_unitdir}` |
|
||
|
|
|
||
|
|
> AP 그룹은 **전적으로 신규 구성**입니다. `dpworldapp`/펌웨어 자원을 건드리지 않으며, `ap0` 전용이라 STA·eth·`dpworldapp`과 충돌하지 않습니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. 제외 / 참고
|
||
|
|
|
||
|
|
| 파일 | 사유 |
|
||
|
|
|---|---|
|
||
|
|
| `deploy/nginx.conf` | **v1.12.1에서 패키지에서 제거됨**. 앱은 `:9090`에서 직접 서비스되므로 reverse proxy 없이 동작합니다. 협력사가 자체 nginx로 `:80` 프런트할 경우, 협력사 설정에서 `proxy_pass http://127.0.0.1:9090/`만 잡으면 됩니다(앱 포트는 `:9090` — 레거시 `:8080` Java app-runner 아님). |
|
||
|
|
| `scripts/board_trace*.sh` | (`deploy/` 밖이지만 참고) board_config를 폴링해 `/tmp`에 기록하는 **개발 진단용** 스크립트 — 운영 배포물에서 제거 권장 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. "충돌" 해소 — 네트워크 적용 통합 3가지 방식
|
||
|
|
|
||
|
|
**"충돌"은 §1-B의 라이브 적용을 *펌웨어 유닛을 빌려서* 수행하기 때문에 발생합니다.** 웹은 적용을 `dpworld-network-apply.service`(펌웨어 소유 유닛) 이름으로 호출하므로, 그 유닛이 우리 스크립트를 실행하게 하려면 유닛을 건드려야 합니다. 아래 3가지 중 선택하세요.
|
||
|
|
|
||
|
|
| 방식 | 설치 파일 | 펌웨어 유닛 접촉 | 라이브 적용 | 비고 |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| **① 저장 전용** | 네트워크 파일 **0개** | **없음(무접촉)** | ✗ (dpworldapp 재기동 시 반영) | 웹은 설정 편집·저장만. 충돌 0. 가장 단순 |
|
||
|
|
| **② 전용 유닛 (권장)** | `dpworld-network-apply-hardened.sh` + 신규 **웹 전용 유닛** | **없음(무접촉)** | ✓ | 웹이 펌웨어 유닛 대신 **자체 유닛**으로 적용. **웹 소규모 코드 변경 필요**(적용 유닛명을 `NET_APPLY_SERVICE` env로 분리 — 현재는 `dpworld-network-apply.service`로 하드코딩) |
|
||
|
|
| **③ 드롭인 override (현재 패키지)** | `dpworld-network-apply-hardened.sh` + 드롭인 3종 | **있음(override)** | ✓ | 펌웨어 유닛의 ExecStart/의존성을 우리 것으로 교체. 이것이 협력사가 본 "충돌" |
|
||
|
|
|
||
|
|
**드롭인 3종(③에서만 사용):**
|
||
|
|
- `dpworld-network-apply.service.d/20-hardened.conf` — 펌웨어 `dpworld-network-apply.service`의 `ExecStart`를 hardened.sh로 교체
|
||
|
|
- `dpworld-network-seed.service.d/20-hardened.conf` — 펌웨어 `dpworld-network-seed.service`(부팅 seed)를 `hardened.sh --boot`로 교체
|
||
|
|
- `dpworld-network-apply-ondemand.conf` — 위 유닛의 `Requires=`(boot-only seed 의존)를 비워 on-demand 기동 허용
|
||
|
|
|
||
|
|
> **권장**: 펌웨어 베이킹(BSP)에서는 하드닝본을 `/usr/bin/dpworld-network-apply.sh` **원본 이름으로 직접 교체**하는 방식이 1차입니다(드롭인 미설치 — `BSP-INTEGRATION.md` §7 ①). 펌웨어 유닛을 못 건드리는 **라이브 디바이스**에서만 드롭인 override(③)를 fallback으로 씁니다. 라이브 적용이 불필요하면 **① 저장 전용**. (③/직접교체 시 §1-B 동작 차이 — Wi-Fi country는 재부팅 시 적용 — 만 합의하면 됨).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. 설치 시 주의 (부분배포 사고 방지)
|
||
|
|
|
||
|
|
- **드롭인(③)을 설치하면 `dpworld-network-apply-hardened.sh`도 반드시 함께** 설치하세요. 드롭인만 있고 스크립트가 없으면 ExecStart가 없는 파일을 가리켜 **펌웨어 네트워크 유닛이 EXEC 실패**합니다(멀쩡하던 적용이 깨짐).
|
||
|
|
- **`web-configurator.service`를 설치하면 앱 본체 `src/`도 함께** 설치하세요. 앱이 없으면 서비스가 재시작 루프에 빠집니다.
|
||
|
|
- **쓰기 가능 경로**: 앱 코드는 read-only rootfs(`/usr/lib/web-configurator`)에 두지만, 아래 런타임 경로는 **쓰기 가능한 영속 파티션**(`/opt`, `/home/root`)에 있어야 합니다.
|
||
|
|
- DB `/home/root/db` · 네트워크 렌더 `/home/root/network` *(dpworldapp과 공유 — 그대로)*
|
||
|
|
- 로그 `/opt/log/dpworldapp`(유닛 `LOG_DIR`) · 펌웨어 staging/upload `/opt/fw_staging`·`/opt/fw_upload` · 설정 백업 `/opt/config_backups` *(유닛 `ReadWritePaths` 참조)*
|
||
|
|
- hardened.sh 상태/로그 `STATE_DIR=/opt/dpworld-network` *(펌웨어 원본엔 없던 신규 경로 — `/opt`가 늦게 마운트되면 로그/reboot 마커만 유실, 적용 자체는 진행). `/opt` 마운트 보장(`RequiresMountsFor=/opt`)을 권장*
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. 전체 파일 분류표 (요약)
|
||
|
|
|
||
|
|
| `deploy/` 파일 | 그룹 | 필요성 | 펌웨어 유닛 접촉 |
|
||
|
|
|---|---|---|---|
|
||
|
|
| `web-configurator.service` | A 코어 | **필수** | 무접촉(신규 유닛) |
|
||
|
|
| `dpworld-network-apply-hardened.sh` | B 네트워크 | 라이브 적용 시 필요 | 무접촉(파일) |
|
||
|
|
| `dpworld-network-apply.service.d/20-hardened.conf` | B 네트워크 | **③에서만** | ★ override |
|
||
|
|
| `dpworld-network-seed.service.d/20-hardened.conf` | B 네트워크 | **③에서만** | ★ override |
|
||
|
|
| `dpworld-network-apply-ondemand.conf` | B 네트워크 | **③에서만** | ★ override |
|
||
|
|
| `dpworld-net-recover.service` | B 네트워크 | 옵션(복구 안전망) | 무접촉(신규 유닛) |
|
||
|
|
| `dpworld-ap-apply.sh` | C AP | AP 시 필수 | 무접촉(파일) |
|
||
|
|
| `dpworld-ap-apply.service` | C AP | AP 시 필수 | 무접촉(신규 유닛) |
|
||
|
|
| `dpworld-hostapd-ap0.service` | C AP | AP 시 필수 | 무접촉(신규 유닛) |
|
||
|
|
| `dpworld-udhcpd-ap0.service` | C AP | AP 시 필수 | 무접촉(신규 유닛) |
|
||
|
|
| `dpworld-ap-seed.service` | C AP | 옵션(재부팅 후 AP 자동복구) | 무접촉(신규 유닛) |
|
||
|
|
|
||
|
|
> ★ 표시(드롭인 3종)만이 펌웨어 소유 유닛을 건드립니다 = "충돌"의 전부. 이 3개를 빼면 펌웨어/`dpworldapp` 자원은 **0개** 건드리지 않습니다.
|
||
|
|
> *`nginx.conf`는 v1.12.1에서 패키지에서 제거됨(§2) — deploy/ 구성요소 아님.*
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 부록: dpworldapp과의 공유·격리 요약
|
||
|
|
|
||
|
|
- **공유(의도된 연동)**: DB `/home/root/db`, 네트워크 렌더 `/home/root/network` — 웹과 `dpworldapp`이 동일 파일 계약(byte 호환)을 공유. 웹이 편집·저장하고 `dpworldapp`이 소비하는 구조(충돌 아님).
|
||
|
|
- **격리(신규, 무접촉)**: 웹 앱(`:9090`), AP(`ap0` 전용 + 방화벽), 복구 유닛, 텔레메트리 Uplink(OS 호스트 라우트만) — 전부 신규 자원.
|
||
|
|
- **유일한 접점**: `dpworld-network-apply.service`/`-seed.service`(펌웨어 소유) — 라이브 적용을 위해 ③ 방식에서만 override. ① 또는 ②를 택하면 이 접점도 사라집니다.
|