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.
 
 
 
 
 
 

16 KiB

BSP 통합 가이드 — Web Configurator v1.12.1

디바이스 이미지(Yocto/OE 등)에 포함하기 위한 커밋 히스토리 없는 클린 스냅샷입니다. 런타임 앱·systemd 유닛·샘플·문서와 optional nginx sample 설정만 들어 있고, 개발/내부 자료와 VCS 이력은 없습니다.


1. 런타임 구조

  • Python 3 애플리케이션, stdlib 전용 — pip·virtualenv·외부 패키지 없음.
  • 실행 진입점: python3 /usr/lib/web-configurator/src/server.py
  • 리슨 포트: 9090 (유닛의 Environment=PORT= 로 변경 가능)
  • 앱은 기본적으로 :9090에서 직접 서비스됩니다. nginx :80 reverse proxy는 optional이며, deploy/nginx.conf는 BSP가 필요할 때 쓰는 sample 설정입니다.
  • 영속 상태 — 패키지에 없음(런타임/다른 컴포넌트가 생성):
    • DB: /home/root/db/dynamic_data.db (DB_PATH)
    • 로그: /opt/log/dpworldapp (LOG_DIR)

nginx optional: scripts/deploy.ps1는 nginx 설정을 설치하거나 수정하지 않습니다. BSP에서 deploy/nginx.conf를 사용할 때만 이미지 레이아웃에 맞게 설치하고, Python 앱 단독 프록시라면 proxy_passhttp://127.0.0.1:9090/ 로 맞추세요.


2. 설치 경로 (do_install)

소스 (이 패키지) 디바이스 설치 위치
src/ ${libdir}/web-configurator/src/ (${libdir} = /usr/lib)
deploy/web-configurator.service ${systemd_system_unitdir}/
deploy/dpworld-*.service ${systemd_system_unitdir}/ (제품이 사용하는 유닛만)
deploy/*.service.d/ ${systemd_system_unitdir}/<unit>.service.d/
deploy/dpworld-*.sh 각 유닛의 ExecStart= 가 가리키는 경로
deploy/nginx.conf Optional nginx sample site config. BSP/firmware가 nginx를 별도로 소유하면 생략 가능

권장 전체 기능 설치 목록:

  • 항상 설치: src/, deploy/web-configurator.service
  • 네트워크 apply 사용 시 (권장 = 직접 교체): deploy/dpworld-network-apply-hardened.sh 의 내용을 /usr/bin/dpworld-network-apply.sh 원본 이름으로 설치(펌웨어 base 스크립트 교체). firmware-native base 유닛(dpworld-network-apply.service/dpworld-network-seed.service)이 그 경로를 호출하므로 자동 적용됨. 이 방식에서는 20-hardened.conf ExecStart override 드롭인은 설치하지 않습니다 (scripts/deploy.ps1 라이브 후적용 fallback 전용 — §7, docs/firmware-boot-hardening.md). 단, 온디맨드 apply 는 웹이 systemctl start dpworld-network-apply.service 로 호출하는데, boot-seed Requires= 가 seed(boot-only oneshot)를 --boot 모드로 재트리거합니다. seed 도 하드닝본이라 드롭인이 없어도 안전 통과하여 systemctl start 는 성공하지만(필수 아님), 그 불필요한 seed --boot 재실행을 회피하려면 10-ondemand.conf 드롭인 베이킹을 권장합니다(완화 overlay) — deploy/dpworld-network-apply-ondemand.conf/lib/systemd/system/dpworld-network-apply.service.d/10-ondemand.conf 로 설치(§7, 아래 참고).
  • Wi-Fi AP 사용 시: deploy/dpworld-ap-apply.service, deploy/dpworld-ap-seed.service, deploy/dpworld-hostapd-ap0.service, deploy/dpworld-udhcpd-ap0.service, deploy/dpworld-ap-apply.sh를 함께 설치
  • 복구 유닛 사용 시: deploy/dpworld-net-recover.service 설치
  • *.sh0755 실행 권한으로 /usr/bin/에 설치

앱 코드 디렉토리 /usr/lib/web-configuratordo_install 이 이미지에 굽는 read-only program code 이므로 아래 쓰기 디렉토리 목록에 포함하지 않습니다.

쓰기 가능 런타임 디렉토리 생성 (recipe do_install / tmpfiles.d / 유닛의 ExecStartPre 중 택1):

/opt/log/dpworldapp  /opt/fw_staging  /opt/fw_upload
/opt/config_backups  /home/root/db    /home/root/network

3. 런타임 의존성 (RDEPENDS)

stdlib 전용 — 앱이 import하는 python3 표준 모듈만 이미지에 포함하면 됩니다. (외부 패키지 없음) OE의 모듈형 python3 기준 예시:

python3-core python3-sqlite3 python3-json python3-netserver python3-netclient
python3-compression python3-crypt python3-logging python3-datetime python3-threading
python3-shell python3-io python3-mime python3-stringold python3-ctypes

실제 import: sqlite3, http(.server), socketserver, socket, urllib, json, gzip, tarfile, zipfile, hashlib, subprocess, shlex, logging, datetime, ipaddress, mimetypes, struct, tempfile, shutil, re, io, os, sys, time, copy, traceback — 사용하는 OE python3 분할 패키지에 맞춰 확인하세요.

추가로 유닛이 런타임에 쓰는 시스템 패키지: nginx reverse proxy를 이미지에서 제공할 때만 nginx. 네트워크/AP 유닛 사용 시 wpa-supplicant, hostapd, udhcpd/busybox, iproute2 등.


4. systemd

SYSTEMD_SERVICE:${PN} = "web-configurator.service"
SYSTEMD_AUTO_ENABLE   = "enable"

제품에서 필요한 dpworld-* 유닛(network-apply, Wi-Fi AP, recovery)을 추가하세요. 전체 기능 이미지에서는 보통 다음처럼 함께 등록합니다:

SYSTEMD_SERVICE:${PN} = "web-configurator.service \
                         dpworld-ap-seed.service \
                         dpworld-hostapd-ap0.service \
                         dpworld-udhcpd-ap0.service"

dpworld-ap-apply.servicedpworld-net-recover.service는 웹 설정기/watchdog이 on-demand로 systemctl start 하므로 [Install] 없이 설치만 하면 됩니다. dpworld-network-apply.service/dpworld-network-seed.service는 firmware-native base 유닛이며 /usr/bin/dpworld-network-apply.sh 를 호출합니다 — 본 패키지는 그 base 스크립트를 하드닝본으로 교체합니다(권장, §7). (펌웨어 원본을 교체할 수 없는 라이브 디바이스에서는 .service.d override 드롭인이 fallback.)


5. 샘플 레시피 — web-configurator_1.12.1.bb

SUMMARY  = "DP World Smart Solutions — Web Configurator"
LICENSE  = "CLOSED"

# 방법 A — 내부 git 서버의 태그 릴리스를 fetch (배포물이 repo 루트에 평탄 배치됨):
SRC_URI  = "git://<internal-host>/<path>/NewWebConfigurator.git;branch=<branch>;protocol=ssh"
SRCREV   = "<v1.12.1 의 sha 또는 tag>"
S        = "${WORKDIR}/git"
# 방법 B — git archive 로 만든 스냅샷 tarball 사용:
#   (git -C <repo> archive v1.12.1 | gzip > web-configurator-v1.12.1.tar.gz)
#   SRC_URI = "file://web-configurator-v1.12.1.tar.gz"
#   S       = "${WORKDIR}"

inherit systemd

RDEPENDS:${PN} += "python3-core python3-sqlite3 python3-json python3-netserver \
                   python3-netclient python3-compression python3-crypt python3-logging \
                   python3-datetime python3-threading python3-shell python3-io \
                   python3-mime"

# Optional: add nginx only if this recipe installs/enables the nginx reverse proxy.
# RDEPENDS:${PN} += "nginx"

SYSTEMD_SERVICE:${PN} = "web-configurator.service"
SYSTEMD_AUTO_ENABLE   = "enable"

do_install() {
    # 애플리케이션 (read-only program code → ${libdir} = /usr/lib)
    install -d ${D}${libdir}/web-configurator
    cp -r ${S}/src ${D}${libdir}/web-configurator/

    # systemd 유닛
    install -d ${D}${systemd_system_unitdir}
    install -m 0644 ${S}/deploy/web-configurator.service ${D}${systemd_system_unitdir}/
    install -m 0644 ${S}/deploy/dpworld-ap-apply.service ${D}${systemd_system_unitdir}/
    install -m 0644 ${S}/deploy/dpworld-ap-seed.service ${D}${systemd_system_unitdir}/
    install -m 0644 ${S}/deploy/dpworld-hostapd-ap0.service ${D}${systemd_system_unitdir}/
    install -m 0644 ${S}/deploy/dpworld-udhcpd-ap0.service ${D}${systemd_system_unitdir}/
    install -m 0644 ${S}/deploy/dpworld-net-recover.service ${D}${systemd_system_unitdir}/

    # 유닛 ExecStart 대상 스크립트
    install -d ${D}${bindir}
    install -m 0755 ${S}/deploy/dpworld-ap-apply.sh ${D}${bindir}/dpworld-ap-apply.sh

    # 네트워크-적용 하드닝 (권장 = 직접 교체):
    #   펌웨어 base 스크립트 /usr/bin/dpworld-network-apply.sh 를 하드닝본으로 교체한다.
    #   firmware-native 한 dpworld-network-apply.service / dpworld-network-seed.service 가
    #   이 경로를 호출하므로 apply·--boot 모두 자동으로 하드닝 동작을 탄다.
    #   ExecStart를 바꾸는 20-hardened.conf override 드롭인은 설치하지 않는다(scripts/deploy.ps1 fallback 전용).
    #   (파일 소유권은 BSP에서 조정 — firmware recipe의 base 파일을 이 패키지가 덮어쓰도록
    #    bbappend 또는 recipe 우선순위로 정리. 자세히 docs/firmware-boot-hardening.md)
    install -m 0755 ${S}/deploy/dpworld-network-apply-hardened.sh \
        ${D}${bindir}/dpworld-network-apply.sh

    # 온디맨드 apply 드롭인 (권장 bake — OPTIONAL 완화, 필수 아님):
    #   web-configurator 가 systemctl start dpworld-network-apply.service 로 온디맨드 호출할 때
    #   boot-seed Requires= 가 seed(boot-only oneshot)를 --boot 로 재트리거한다. seed 도 하드닝본이라
    #   이 드롭인이 없어도 안전 통과(systemctl start 성공)한다. 이 드롭인은 Requires= 를 비워 그
    #   불필요한 seed --boot 재실행만 회피하는 완화 overlay 이다(결함 fix 아님).
    install -d ${D}${systemd_system_unitdir}/dpworld-network-apply.service.d
    install -m 0644 ${S}/deploy/dpworld-network-apply-ondemand.conf \
        ${D}${systemd_system_unitdir}/dpworld-network-apply.service.d/10-ondemand.conf

    # Fallback (라이브 후적용 전용 — 베이킹 시 설치하지 않음):
    #   펌웨어 원본을 교체할 수 없는 경우에만, 하드닝본을 원래 -hardened 이름으로 설치하고
    #   deploy/dpworld-network-{apply,seed}.service.d/20-hardened.conf 드롭인 2개로
    #   base 유닛의 ExecStart 를 override 한다.

    # Optional nginx site config.
    # scripts/deploy.ps1 does not use this file. Skip this block if firmware/BSP
    # owns nginx, or if the device will access the app directly on :9090.
    if [ -f ${S}/deploy/nginx.conf ]; then
        install -d ${D}${sysconfdir}/nginx
        install -m 0644 ${S}/deploy/nginx.conf ${D}${sysconfdir}/nginx/web-configurator.conf
    fi

    # 쓰기 가능 런타임 디렉토리
    install -d ${D}/opt/log/dpworldapp ${D}/opt/fw_staging ${D}/opt/fw_upload \
               ${D}/opt/config_backups ${D}/home/root/db ${D}/home/root/network
}

FILES:${PN} += "${libdir}/web-configurator /opt/log ${systemd_system_unitdir} \
                /opt/fw_staging /opt/fw_upload /opt/config_backups \
                /home/root/db /home/root/network ${bindir}/dpworld-*.sh \
                ${sysconfdir}/nginx"

6. 부팅 후 동작 확인 (smoke test)

systemctl status web-configurator        # active (running)
curl -fsS http://127.0.0.1:9090/ | head  # 앱 응답
curl -fsS http://127.0.0.1/ | head       # optional: nginx 경유 사용 시

7. firmware-native 전제 + 네트워크-적용 하드닝 통합

firmware가 제공하는 것 (이 패키지에 미포함)

  • base 네트워크-적용 유닛dpworld-network-apply.service, dpworld-network-seed.service. 이 유닛들은 /usr/bin/dpworld-network-apply.sh 를 호출합니다(no-arg / --boot).
  • dpworldapp(텔레메트리 바이너리), (전환기의 레거시 app-runner) — firmware-native.
  • nginx — 제품 이미지가 :80 reverse proxy를 제공할 때만. 앱을 :9090으로 직접 접근하면 불필요.

네트워크-적용 하드닝본 통합 — ① 직접 교체(권장) vs ② override(fallback)

펌웨어 base /usr/bin/dpworld-network-apply.sh 에는 WiFi country 변경 시 modprobe -r wlan 라이브 재로드 경로가 있어 QCA6490에서 PMU 워치독 재부팅 루프를 유발한 이력이 있습니다. deploy/dpworld-network-apply-hardened.sh 가 이를 제거한 완전 대체본입니다.

불변식(권장이 아니라 필수): canonical /usr/bin/dpworld-network-apply.sh반드시 하드닝본이어야 합니다(①/② 중 하나로 보장). 웹의 온디맨드 apply(systemctl start dpworld-network-apply.service)는 이 경로 + Requires=seed(→ seed --boot)를 타므로, un-hardened 로 남기면 modprobe -r wlan → 부트루프가 재발합니다. 아래 표의 '권장'은 ①vs② 방식 선택의 권장일 뿐, 하드닝 자체는 선택이 아닙니다(Codex Q1 잔여 리스크).

① 직접 교체 (BSP 베이킹, 권장) ② override (라이브 후적용, fallback)
대상 펌웨어 이미지를 빌드하는 협력사 이미 구워진 디바이스(우리 deploy.ps1)
방법 하드닝본 내용을 /usr/bin/dpworld-network-apply.sh 원본 이름으로 설치(원본 교체) 하드닝본을 …-hardened.sh 로 두고 .service.d/20-hardened.conf 드롭인 2개로 ExecStart 교체
드롭인 (하드닝) 없음 (직접 교체는 ExecStart override 드롭인 불필요) 20-hardened.conf 2개만 설치
드롭인 (온디맨드) 10-ondemand.conf 권장 bake (완화 overlay·필수 아님 — systemctl start 는 없어도 성공, 불필요한 seed --boot 재트리거만 회피) 10-ondemand.conf 권장 bake (동일)
효과 base 유닛이 그대로 하드닝 스크립트를 실행 base 유닛의 ExecStart가 하드닝본으로 바뀜

온디맨드 드롭인 10-ondemand.conf (권장 bake — OPTIONAL 완화, 필수 아님): web-configurator/watchdog 는 온디맨드 네트워크 적용을 systemctl start dpworld-network-apply.service 로 호출합니다. 이 base 유닛은 Requires=dpworld-network-seed.service(boot-only oneshot)를 걸어 온디맨드 start 시 seed 를 --boot 로 재트리거하지만, seed 도 하드닝본이라 드롭인이 없어도 안전 통과합니다(systemctl start 성공, 'Dependency failed' 0). 이 드롭인은 Requires= 를 비워 그 불필요한 seed --boot 재실행만 회피하는 완화 overlay 입니다. deploy/dpworld-network-apply-ondemand.conf/lib/systemd/system/dpworld-network-apply.service.d/10-ondemand.conf 로 설치(①·② 양쪽 모두 권장).

참고 (2026-07-01 .56 실측): 이 드롭인은 현재 .56 이미지에 미baked. 없어도 systemctl start dpworld-network-apply.service 는 성공함(Requires=seed 로 seed --boot 가 재트리거되나 seed 도 하드닝본이라 안전 통과). 다만 매 런타임 apply 마다 seed --boot 가 재실행되는 부수효과가 있어, 이 드롭인(또는 seed RemainAfterExit=yes) baking 이 권장됨.

절차 상세: docs/firmware-boot-hardening.md "펌웨어 베이킹 (BSP) — 원본 교체 방법".

이 패키지가 소유·제공하는 스크립트 (모두 포함됨)

스크립트 설치 위치(권장 ①) 호출 주체
deploy/dpworld-ap-apply.sh /usr/bin/dpworld-ap-apply.sh dpworld-ap-apply.service, dpworld-ap-seed.service
deploy/dpworld-network-apply-hardened.sh /usr/bin/dpworld-network-apply.sh (원본 교체) firmware-native dpworld-network-apply.service / dpworld-network-seed.service
deploy/dpworld-network-apply-ondemand.conf /lib/systemd/system/dpworld-network-apply.service.d/10-ondemand.conf (권장 bake) web-configurator/watchdog 온디맨드 systemctl start dpworld-network-apply.service

fallback(②) 사용 시에는 …-hardened.sh 이름으로 설치하고 .service.d 드롭인 2개(deploy/dpworld-network-apply.service.d/, deploy/dpworld-network-seed.service.d/)를 함께 둡니다.

웹 설정기 앱이 런타임에 호출하는 유닛

server.py 는 다음을 systemctl start 로 호출합니다: dpworld-network-apply.service(firmware base 유닛 — 교체된 하드닝 스크립트 실행), dpworld-ap-apply.service, dpworld-hostapd-ap0.service, dpworld-udhcpd-ap0.service, dpworld-net-recover.service. → base 네트워크-적용 유닛(firmware-native)을 제외하면 모두 본 패키지에 포함됩니다.