secubox-deb/remote-ui/round/deploy.sh
CyberMind 7c37415f88
feat(remote-ui): Phase 1 — extract common/ shared core (ref #127)
* feat(remote-ui/common): scaffold shared-core directory (ref #127)

* feat(remote-ui/common): extract palette.css from round/ (ref #127)

* fix(remote-ui/common): trim palette.css to spec (6 module + 8 C3BOX tokens) (ref #127)

* feat(remote-ui/common): extract base.css verbatim from round/ (ref #127)

* feat(remote-ui/common): extract ICONS to icons.js (ref #127)

* docs(remote-ui/common): correct icons.js header comment — sizes are {22,48,96} not 128 (ref #127)

* feat(remote-ui/common): extract RINGS + CX/CY/SA to modules-table.js (ref #127)

* feat(remote-ui/common): extract CFG to config.js (replaces jwt-helper.js per #127 plan revision)

* feat(remote-ui/common): extract TransportManager with onModuleTap/onTransportChange hooks (ref #127)

* feat(remote-ui/common): extract SIM + simStep to sim.js (ref #127)

* feat(remote-ui/common): move 24 SecuBox module PNG icons to common/assets/icons/ (ref #127)

* feat(remote-ui/common): move secubox-otg-gadget.sh, add GADGET_NAME env override + arm64 serial fallback (ref #127)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(remote-ui/common): trim whitespace from device-tree serial-number read (ref #127)

* feat(remote-ui/common): move secubox-otg-host-up.sh + variant-aware comment (ref #127)

* refactor(remote-ui/round): consume common/ via <link>/<script> tags (ref #127)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(secubox-system): add form_factor to RemoteUIConnectedRequest with TDD (ref #127)

* feat(remote-ui/round): deploy.sh bundles common/ alongside round/ (ref #127)

* fix(remote-ui/round): deploy.sh COMMON_SRC path resolution + rsync --delete (ref #127)

* feat(remote-ui/round): build-eye-remote-image.sh embeds common/ + nginx /common/ alias (ref #127)

* docs(remote-ui): document common/ dependency in round/ docs (ref #127)

* docs(remote-ui/round): clarify palette.css is forward-looking (ref #127)

* docs(remote-ui): Task 18 regression-gate report — structural verification (ref #127)

Full diffoscope gate blocked by missing hyperpixel2r.dtbo prerequisite.
Structural equivalence verified instead: Phase 1 changes are purely
additive (common/ embed + nginx /common/ alias + extracted JS/CSS/icons),
no behavioural change to round/'s existing logic.

User must run the full image diffoscope manually after sourcing the
hyperpixel2r.dtbo blob, before final merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci(eye-remote): bump workflow VERSION env 2.2.0 → 2.2.1 (ref #127)

Pre-existing drift: build-eye-remote-image.sh writes
secubox-eye-remote-2.2.1.img but the workflow's Compress/Checksum/
Upload steps reference ${{ env.VERSION }} = 2.2.0, so the compress
step fails with "No such file or directory" after a successful build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 05:59:40 +02:00

242 lines
12 KiB
Bash
Executable File

#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════════════
# SecuBox Remote UI — deploy.sh
# Déploie/met à jour le dashboard sur un RPi Zero W déjà configuré
#
# CyberMind — https://cybermind.fr
# Author: Gérald Kerma <gandalf@gk2.net>
# License: Proprietary / ANSSI CSPN candidate
# ═══════════════════════════════════════════════════════════════════════════════
set -euo pipefail
# ══════════════════════════════════════════════════════════════════════════════
# CONFIGURATION
# ══════════════════════════════════════════════════════════════════════════════
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VERSION="1.0.0"
INDEX_HTML="$SCRIPT_DIR/index.html"
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() { echo -e "${GREEN}[deploy]${NC} $*"; }
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
err() { echo -e "${RED}[error]${NC} $*" >&2; }
# Valeurs par défaut
HOST=""
USER="secubox"
PORT=22
API_URL=""
API_PASS=""
SIMULATE=""
# ══════════════════════════════════════════════════════════════════════════════
# AIDE
# ══════════════════════════════════════════════════════════════════════════════
usage() {
cat << EOF
SecuBox Remote UI — Déploiement Dashboard RPi Zero W
Usage: $0 [OPTIONS]
Options requises:
-h, --host HOST Adresse IP ou hostname du RPi Zero W
Options facultatives:
-u, --user USER Utilisateur SSH (défaut: $USER)
-p, --port PORT Port SSH (défaut: $PORT)
--api-url URL URL de l'API SecuBox (ex: http://192.168.1.1:8000)
--api-pass PASS Mot de passe API pour le dashboard
--sim Activer le mode simulation (hors-ligne)
--no-sim Désactiver le mode simulation
--help Afficher cette aide
Exemples:
$0 -h secubox-round.local --api-url http://192.168.1.1:8000 --api-pass motdepasse
$0 -h 192.168.1.42 -u pi --sim
EOF
exit 0
}
# ══════════════════════════════════════════════════════════════════════════════
# PARSING ARGUMENTS
# ══════════════════════════════════════════════════════════════════════════════
while [[ $# -gt 0 ]]; do
case $1 in
-h|--host) HOST="$2"; shift 2 ;;
-u|--user) USER="$2"; shift 2 ;;
-p|--port) PORT="$2"; shift 2 ;;
--api-url) API_URL="$2"; shift 2 ;;
--api-pass) API_PASS="$2"; shift 2 ;;
--sim) SIMULATE="true"; shift ;;
--no-sim) SIMULATE="false"; shift ;;
--help) usage ;;
*) err "Option inconnue: $1"; exit 1 ;;
esac
done
# ══════════════════════════════════════════════════════════════════════════════
# VALIDATIONS
# ══════════════════════════════════════════════════════════════════════════════
if [[ -z "$HOST" ]]; then
err "Adresse du RPi Zero W requise (-h)"
exit 1
fi
if [[ ! -f "$INDEX_HTML" ]]; then
err "index.html non trouvé: $INDEX_HTML"
exit 1
fi
# ══════════════════════════════════════════════════════════════════════════════
# PRÉPARATION DU FICHIER
# ══════════════════════════════════════════════════════════════════════════════
log "═══════════════════════════════════════════════════════════════"
log "SecuBox Remote UI — Déploiement v$VERSION"
log "═══════════════════════════════════════════════════════════════"
log ""
log "Cible: ${USER}@${HOST}:${PORT}"
log "API URL: ${API_URL:-<non modifié>}"
log "Simulate: ${SIMULATE:-<non modifié>}"
log ""
# Créer une copie temporaire pour les patches
TEMP_HTML=$(mktemp)
cp "$INDEX_HTML" "$TEMP_HTML"
# Patch CFG.API_BASE si fourni
if [[ -n "$API_URL" ]]; then
log "Patch API_BASE → $API_URL"
sed -i "s|API_BASE: '[^']*'|API_BASE: '$API_URL'|" "$TEMP_HTML"
fi
# Patch CFG.LOGIN_PASS si fourni
if [[ -n "$API_PASS" ]]; then
log "Patch LOGIN_PASS..."
sed -i "s|LOGIN_PASS: '[^']*'|LOGIN_PASS: '$API_PASS'|" "$TEMP_HTML"
fi
# Patch CFG.SIMULATE si demandé
if [[ -n "$SIMULATE" ]]; then
log "Patch SIMULATE → $SIMULATE"
sed -i "s|SIMULATE: [a-z]*|SIMULATE: $SIMULATE|" "$TEMP_HTML"
fi
# ══════════════════════════════════════════════════════════════════════════════
# TEST CONNEXION SSH
# ══════════════════════════════════════════════════════════════════════════════
log "Test connexion SSH..."
if ! ssh -p "$PORT" -o ConnectTimeout=10 -o BatchMode=yes "${USER}@${HOST}" "echo ok" &>/dev/null; then
err "Impossible de se connecter à ${USER}@${HOST}:${PORT}"
err "Vérifiez que:"
err " - Le RPi est démarré et connecté au réseau"
err " - SSH est activé"
err " - Votre clé SSH est autorisée"
rm -f "$TEMP_HTML"
exit 1
fi
log "Connexion SSH OK"
# ══════════════════════════════════════════════════════════════════════════════
# DÉPLOIEMENT
# ══════════════════════════════════════════════════════════════════════════════
log "Copie de common/ (icons, css, js, shell)..."
# Round/index.html references ../common/css/* and ../common/js/* (rel paths).
# On the device: /var/www/common/ must be a sibling of /var/www/secubox-round/.
COMMON_SRC="$(dirname "$SCRIPT_DIR")/common"
if [ ! -d "$COMMON_SRC" ]; then
err "Répertoire common/ introuvable: $COMMON_SRC"
rm -f "$TEMP_HTML"
exit 1
fi
rsync -avz --delete -e "ssh -p $PORT" "$COMMON_SRC/" "${USER}@${HOST}:/tmp/secubox-common/"
log "Copie du dashboard..."
scp -P "$PORT" "$TEMP_HTML" "${USER}@${HOST}:/tmp/index.html"
log "Installation..."
ssh -p "$PORT" "${USER}@${HOST}" << 'REMOTE_SCRIPT'
set -e
# Move common/ payload into /var/www/common/
sudo rm -rf /var/www/common
sudo mv /tmp/secubox-common /var/www/common
sudo chown -R www-data:www-data /var/www/common
# Copier vers le répertoire web
sudo cp /tmp/index.html /var/www/secubox-round/index.html
sudo chown www-data:www-data /var/www/secubox-round/index.html
rm /tmp/index.html
# Recharger nginx
sudo systemctl reload nginx
echo "OK"
REMOTE_SCRIPT
# ══════════════════════════════════════════════════════════════════════════════
# PATCH NGINX PROXY (si API_URL fourni)
# ══════════════════════════════════════════════════════════════════════════════
if [[ -n "$API_URL" ]]; then
# Extraire l'hôte et le port de l'URL
API_HOST=$(echo "$API_URL" | sed -E 's|https?://([^:/]+).*|\1|')
API_PORT=$(echo "$API_URL" | sed -E 's|https?://[^:]+:?([0-9]*).*|\1|')
API_PORT=${API_PORT:-8000}
log "Patch nginx proxy → ${API_HOST}:${API_PORT}"
ssh -p "$PORT" "${USER}@${HOST}" << REMOTE_NGINX
set -e
sudo sed -i "s|proxy_pass http://[^;]*;|proxy_pass http://${API_HOST}:${API_PORT};|" /etc/nginx/sites-available/secubox-round
sudo nginx -t
sudo systemctl reload nginx
REMOTE_NGINX
fi
# ══════════════════════════════════════════════════════════════════════════════
# TEST HTTP
# ══════════════════════════════════════════════════════════════════════════════
log "Test HTTP..."
HTTP_CODE=$(ssh -p "$PORT" "${USER}@${HOST}" "curl -s -o /dev/null -w '%{http_code}' http://localhost:8080" 2>/dev/null || echo "000")
if [[ "$HTTP_CODE" == "200" ]]; then
log "Test HTTP OK (200)"
else
warn "Test HTTP retourne $HTTP_CODE (attendu 200)"
fi
# Nettoyage
rm -f "$TEMP_HTML"
# ══════════════════════════════════════════════════════════════════════════════
# RÉSUMÉ
# ══════════════════════════════════════════════════════════════════════════════
log ""
log "═══════════════════════════════════════════════════════════════"
log "Déploiement terminé !"
log "═══════════════════════════════════════════════════════════════"
log ""
log "Dashboard accessible sur le HyperPixel 2.1 Round"
log "Debug via: ssh ${USER}@${HOST} 'journalctl -u lightdm -f'"
log ""
if [[ "$SIMULATE" == "true" ]]; then
warn "Mode SIMULATION activé — données fictives"
fi