fix(deploy): 노드/디스플레이 setup.sh 위치-독립화 — flatten 불필요

systemd 유닛의 /home/pi/<subdir> 경로를 설치 시점에 setup.sh가 $BASE=$(pwd) 로 sed 치환.
번들 폴더를 이름 그대로 /home/pi 아래 어디에 두든(USB 통째 복사 포함) 동작 → flatten 단계 제거.

- build_node_setup_sh: copy_block 을 sed "s#/home/pi/#$BASE/#g" | sudo tee 로 교체, BASE 추가
- display setup.sh: 동일 방식(+ 기존 유닛 경로 버그 수정 — /home/pi/display 하드코딩이
  실제 설치경로와 불일치해 서비스 기동 실패하던 것을 $BASE 치환으로 해소)
- SETUP.md(노드·디스플레이): flatten 지침 제거, USB '폴더째 복사 후 cd·실행' 로 갱신
This commit is contained in:
cw2007 2026-07-19 13:37:20 +09:00
parent a1bd51672d
commit 3fda1f2af6

View file

@ -188,8 +188,11 @@ def build_node_setup_sh(meta: dict) -> str:
install_block = "\n".join(
f'echo " -> {sp["sub"]}"\n( cd "{sp["sub"]}" && chmod +x install.sh && ./install.sh )'
for sp in specs)
# Inject THIS bundle's real path ($BASE) into each unit's /home/pi/<sub> paths at install
# time, so the node works from wherever it was copied (no flatten to /home/pi required).
copy_block = "\n".join(
f'sudo cp "{sp["sub"]}/systemd/{sp["unit"]}.service" /etc/systemd/system/'
f'sed "s#/home/pi/#${{BASE}}/#g" "{sp["sub"]}/systemd/{sp["unit"]}.service" '
f'| sudo tee "/etc/systemd/system/{sp["unit"]}.service" >/dev/null'
for sp in specs)
enable_block = "\n".join(f'sudo systemctl enable --now {sp["unit"]}' for sp in specs)
verify_block = "\n".join(
@ -199,13 +202,16 @@ def build_node_setup_sh(meta: dict) -> str:
return f'''#!/usr/bin/env bash
# =============================================================================
# setup.sh - combined fresh install for {meta["device_id"]} ({subs})
# Run as the pi user from /home/pi: bash setup.sh (do NOT run with sudo - sudo is used internally)
# The service subdirs must sit at /home/pi/<subdir> (the stock systemd units reference those paths).
# Run as the pi user (never sudo): bash setup.sh
# Location-independent: the systemd unit paths are auto-set to THIS folder's real path at
# install time, so the bundle can live anywhere under /home/pi (no flatten needed - copy the
# whole folder as-is, keep its name, cd in, run).
# Order: install every service -> register + enable all -> verify all -> harden ONCE (SSH lockdown).
# On any failure set -e stops BEFORE hardening -> SSH stays up for debugging.
# =============================================================================
set -euo pipefail
cd "$(dirname "$0")"
BASE="$(pwd)" # actual install path of this bundle -> injected into the unit paths below
if [ "$(id -u)" -eq 0 ]; then
echo "[ERROR] Run as the pi user without sudo: bash setup.sh" >&2
@ -251,18 +257,17 @@ Wiring / pinout: open {wiring} in a browser (self-contained - viewable offline).
## One-shot combined install (recommended)
The service subfolders must end up at **/home/pi/{subs}** - the stock systemd units reference
those exact paths. Flatten the node bundle straight into `/home/pi`:
**No flatten needed.** `setup.sh` auto-sets the systemd unit paths to wherever this folder
actually sits, so copy the whole folder as-is (keep its name `{name}`) anywhere under `/home/pi`
and run it. Subfolders end up at `/home/pi/{name}/{subs}` and that is fine.
```bash
# 1. Copy the node bundle to the Pi, then flatten it into /home/pi
scp -r {name} pi@<PI_IP>:/home/pi/
ssh pi@<PI_IP>
mv ~/{name}/* ~/ && rmdir ~/{name}
# 1. Copy this whole folder under /home/pi (USB or scp; keep the folder name)
# USB example: cp -r /media/pi/<USB_LABEL>/{name} /home/pi/
# scp example: scp -r {name} pi@<PI_IP>:/home/pi/
# 2. All at once: install every service -> register + enable -> verify -> harden
cd ~ && bash setup.sh
# (do NOT prefix with sudo - sudo is used internally)
# 2. Enter the folder and run (do NOT prefix with sudo - sudo is used internally)
cd /home/pi/{name} && bash setup.sh
```
`setup.sh` installs every service, registers + enables all units (single daemon-reload), verifies each
@ -345,6 +350,7 @@ DEVICE_NAME = "{meta["device_id"]}"
# =============================================================================
set -euo pipefail
cd "$(dirname "$0")"
BASE="$(pwd)" # actual install path -> injected into the unit path below (no fixed /home/pi/display)
if [ "$(id -u)" -eq 0 ]; then
echo "[ERROR] Run as the pi user without sudo: bash setup.sh" >&2
@ -354,8 +360,8 @@ fi
echo "== [1/4] Install packages + venv =="
chmod +x install.sh && ./install.sh
echo "== [2/4] Register systemd service =="
sudo cp systemd/{meta["service"]}.service /etc/systemd/system/
echo "== [2/4] Register systemd service (path auto-set to this folder) =="
sed "s#/home/pi/display#${{BASE}}#g" systemd/{meta["service"]}.service | sudo tee /etc/systemd/system/{meta["service"]}.service >/dev/null
sudo systemctl daemon-reload
sudo systemctl enable --now {meta["service"]}
@ -380,13 +386,16 @@ Wiring / pinout: open `WIRING.html` in the same folder in a browser (self-contai
## One-shot install (recommended)
```bash
# 1. Copy this folder to the Pi
scp -r {name} pi@<PI_IP>:/home/pi/{src}
**No fixed path required.** `setup.sh` auto-sets the systemd unit path to wherever this folder
sits, so copy it as-is (USB or scp) under `/home/pi` and run.
# 2. All at once: install -> register service -> verify -> harden
cd /home/pi/{src} && bash setup.sh
# (do NOT prefix with sudo - sudo is used internally)
```bash
# 1. Copy this whole folder under /home/pi (USB or scp; keep the folder name)
# USB example: cp -r /media/pi/<USB_LABEL>/{name} /home/pi/
# scp example: scp -r {name} pi@<PI_IP>:/home/pi/
# 2. Enter the folder and run (do NOT prefix with sudo - sudo is used internally)
cd /home/pi/{name} && bash setup.sh
```
`setup.sh` runs 4 stages automatically and **stops before hardening if the verify (stage 3) fails**