Sync wiki with docs/wiki - SecuBox OS as main product

- Home.md: SecuBox OS Appliance as main product
- _Sidebar.md: Eye Remote moved to Addons section
- Eye-Remote.md: Marked as optional addon
- Added new pages: Architecture-Boot, Design-System, Developer-Guide
- Added Eye-Remote documentation pages

Wiki now focuses on SecuBox OS with Eye Remote as optional addon.
CyberMind-FR 2026-04-26 20:43:37 +02:00
parent 46b6c58564
commit 482a6e615f
12 changed files with 5197 additions and 538 deletions

150
Architecture-Boot.md Normal file

@ -0,0 +1,150 @@
# Boot Architecture
**SecuBox-DEB** uses a five-layer boot chain from hardware firmware to user space. Three exclusive execution modes are available: maintenance (`PROMPT`), display (`KIOSK`), or production (`API`).
---
## Boot Chain Overview
### Layer 1 — HW / BootLoader
| Platform | Firmware | Notes |
|----------|----------|-------|
| Lenovo ThinkCentre M710q | BIOS/UEFI | x86_64, Secure Boot capable |
| MOCHAbin (Armada 7040) | U-Boot | ARM64, eMMC or NVMe boot |
| ESPRESSObin (Armada 3720) | U-Boot | ARM64, SD or eMMC boot |
### Layer 2 — OS / UEFI (GRUB2)
GRUB2 handles kernel selection, signature verification (Secure Boot), and optional TPM2 unsealing (`tpm2_unseal`).
**CSPN Compliance Points:**
- `/boot` partition is unencrypted (FAT32/ext4) but protected by UEFI signature verification
- Kernel command line parameters are locked in production
- GRUB password is mandatory on production targets
### Layer 3 — Kernel + InitRamfs
#### Hardened Linux Kernel
```
CONFIG_SECURITY_LOCKDOWN_LSM=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_SHA512=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_RANDOMIZE_BASE=y # KASLR
```
Built-in modules: `nftables`, `WireGuard`, `eBPF` (restricted), MOCHAbin network drivers (mvneta/mvpp2).
#### InitRamfs Operations
1. Mount encrypted LUKS2 disk (`cryptsetup luksOpen`)
2. Verify ZKP pre-mount proof (GK·HAM-HASH L1)
3. Mount encrypted root on `/sysroot`
4. `switch_root` to Rootfs
### Layer 4 — Rootfs / INIT (systemd)
After `pivot_root`, systemd orchestrates the 10-phase SecuBox-DEB startup:
| Phase | Services | SecuBox Pairs |
|-------|----------|---------------|
| 1 — Network | nftables, WireGuard, Tailscale | MESH↔AUTH |
| 2 — Perimeter Security | CrowdSec, HAProxy | WALL↔MIND |
| 3 — DPI dual-stream | nDPId (active/shadow) | WALL↔MIND |
| 4 — Runtime API | FastAPI/Uvicorn, 4R buffer | BOOT↔ROOT |
| 5 — ZKP auth | GK·HAM-HASH (L1/L2/L3) | BOOT↔ROOT |
| 6 — MirrorNet P2P | WireGuard + did:plc | MESH↔AUTH |
| 7 — Notarization | ALERTE·DÉPÔT blind notarization | WALL↔MIND |
| 8 — Display | HyperPixel / RPi Zero coprocessor | MESH↔AUTH |
| 9 — Monitoring | Metrics, alerts, SIEM | WALL↔MIND |
| 10 — Finalization | Health-check, seal TPM2 | BOOT↔ROOT |
---
## Execution Modes
### PROMPT `<LOG>` — Maintenance Mode
**Target:** `secubox-prompt.target`
- Shell access via physical console or restricted SSH
- Full audit logging (`auditd` + `systemd-journal`, 90-day retention)
- Production services (API, DPI, MirrorNet) are stopped
```bash
echo "MODE=PROMPT" > /etc/secubox/runtime.conf
systemctl isolate secubox-prompt.target
```
### KIOSK `[UI]` — Display Mode
**Target:** `secubox-kiosk.target`
- Locked UI for metrics display on HyperPixel
- No shell access, no inbound network interfaces
- Communication via Unix socket (read-only)
- Auto-restart on crash
```bash
echo "MODE=KIOSK" > /etc/secubox/runtime.conf
systemctl isolate secubox-kiosk.target
```
### API `(RT)` — Production Mode
**Target:** `secubox-api.target` (default)
- FastAPI/Uvicorn on Unix socket (HAProxy TLS frontend)
- 4R double-buffer active on L2
- nDPId dual-stream listening
- CrowdSec in agent mode
- No interactive shell, no external SSH
```bash
echo "MODE=API" > /etc/secubox/runtime.conf
systemctl isolate secubox-api.target
```
---
## Module Color Correspondence
| Color | Hex | Layer / Mode |
|-------|-----|--------------|
| BOOT | `#803018` | HW / BootLoader |
| WALL | `#9A6010` | OS / UEFI |
| MIND | `#3D35A0` | Kernel + InitRamfs |
| ROOT | `#0A5840` | Rootfs / INIT — API Mode |
| MESH | `#104A88` | KIOSK Mode [UI] |
| AUTH | `#C04E24` | PROMPT Mode \<LOG\> |
---
## CSPN Control Points
- [ ] Kernel and module signatures verified by Secure Boot
- [ ] InitRD without plaintext secrets (`lsinitrd | grep -i key`)
- [ ] TPM2 sealing to PCR 0+7+14 validated after kernel updates
- [ ] PROMPT mode only accessible via physical console or certificate SSH
- [ ] Audit logs exported and signed before each PROMPT session
- [ ] API mode won't start if ZKP L1 proof fails
- [ ] Network isolation between modes verified by `nft list ruleset`
---
## Bootstrap Device (Eye Remote v2.1+)
The Eye Remote can function as a **boot device** for MOCHAbin and ESPRESSObin systems:
- **Mass Storage LUN** — U-Boot loads kernel/DTB/initrd from active slot
- **TFTP Shadow** — Test new images before atomic promotion
- **Safe Recovery** — Fallback boot when internal storage is corrupted
- **A/B Slot Management** — Automatic rollback on boot failure
See [[Eye-Remote-Bootstrap]] for full implementation details.
---
*See also: [[Architecture-Security]], [[Architecture-Modules]], [[Eye-Remote-Bootstrap]]*

184
Design-System.md Normal file

@ -0,0 +1,184 @@
# Design System
SecuBox uses a **six-module color system** with complementary pairs for visual consistency across all interfaces.
---
## Module Colors
| Module | Code | Color | Hex | Description |
|--------|------|-------|-----|-------------|
| **AUTH** | 01 | Orange (Coral Auth) | `#C04E24` | Authentication, zero-trust |
| **WALL** | 02 | Yellow (Amber Shield) | `#9A6010` | Firewall, nftables |
| **BOOT** | 03 | Red (Coral Launch) | `#803018` | Deployment, provisioning |
| **MIND** | 04 | Violet (Violet Mind) | `#3D35A0` | AI, behavioral analysis, nDPId |
| **ROOT** | 05 | Green (Teal Root) | `#0A5840` | Terminal CLI, Debian system |
| **MESH** | 06 | Blue (Blue Mesh) | `#104A88` | Network, WireGuard, Tailscale |
### Complementary Pairs
- **Red ↔ Green** (BOOT ↔ ROOT) — System deployment and operation
- **Yellow ↔ Violet** (WALL ↔ MIND) — Security and intelligence
- **Blue ↔ Orange** (MESH ↔ AUTH) — Network and access control
---
## Color Palette Details
### AUTH (Orange)
```css
--auth-main: #C04E24;
--auth-light: #E8845A;
--auth-xlt: #FAECE7;
--auth-dark: #7A2A10;
```
### WALL (Yellow/Amber)
```css
--wall-main: #9A6010;
--wall-light: #CC8820;
--wall-xlt: #FDF3E0;
--wall-dark: #5A3808;
```
### BOOT (Red)
```css
--boot-main: #803018;
--boot-light: #C06040;
--boot-xlt: #FAECE7;
--boot-dark: #5A1E0A;
```
### MIND (Violet)
```css
--mind-main: #3D35A0;
--mind-light: #7068D0;
--mind-xlt: #EEEDFE;
--mind-dark: #241D6A;
```
### ROOT (Green/Teal)
```css
--root-main: #0A5840;
--root-light: #148C66;
--root-xlt: #E1F5EE;
--root-dark: #063828;
```
### MESH (Blue)
```css
--mesh-main: #104A88;
--mesh-light: #2C70C0;
--mesh-xlt: #E6F1FB;
--mesh-dark: #08305A;
```
---
## Light Theme Base Colors
```css
--bg: #FFFFFF;
--surface: #FAFAF8;
--surface2: #F4F3EF;
--border: #E2E0D8;
--border2: #C8C6BE;
--text: #1A1A18;
--muted: #6B6963;
```
---
## Dark Theme (Eye Remote / Dashboard)
```css
--cosmos-black: #0a0a0f;
--gold-hermetic: #c9a84c;
--cinnabar: #e63946;
--matrix-green: #00ff41;
--void-purple: #6e40c9;
--cyber-cyan: #00d4ff;
--text-primary: #e8e6d9;
--text-muted: #6b6b7a;
```
---
## Typography
### Font Stack
- **Display/Heading**: Space Grotesk (300-700)
- **Body**: Space Grotesk 400
- **Monospace/Code**: JetBrains Mono (400, 700)
### Usage
```css
/* Display - titles */
font-size: 56px;
font-weight: 700;
letter-spacing: -2px;
color: var(--root-main);
/* Heading */
font-size: 24px;
font-weight: 600;
letter-spacing: -0.4px;
/* Body */
font-size: 14-16px;
font-weight: 400;
line-height: 1.6-1.7;
/* Code/Terminal */
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
```
---
## Brand Identities
| Brand | Color | Usage |
|-------|-------|-------|
| **SecuBox·** | Green (Root) | Main product brand |
| **Gondwana** | Violet (Mind) | Public/external brand |
| **CyberMind** | Orange (Auth) | Internal/confidential brand |
---
## Module Icons/Symbols
| Module | Symbol | Description |
|--------|--------|-------------|
| AUTH | Hexagonal target | Controlled access, verified identity |
| WALL | Flaming brick wall | nftables, inbound/outbound rules |
| BOOT | Rocket | Provisioning, fast boot, deployment |
| MIND | Robot | Automation, behavioral analysis |
| ROOT | $>_ prompt | Console access, low-level system |
| MESH | Network gear | WireGuard, Tailscale, mesh topology |
---
## Spacing System
| Size | Pixels | Usage |
|------|--------|-------|
| XS | 4px | Icon gaps |
| S | 8px | Chips |
| M | 16px | Padding |
| L | 24px | Sections |
| XL | 40px | Margins |
| 2XL | 56px | Cover |
---
## Grid System
- 12-column grid
- Gap: 8px
- Border radius: 14px (cards), 6px (swatches), 3px (small elements)
---
*© 2026 CyberMind · Notre-Dame-du-Cruet, Savoie*

196
Developer-Guide.md Normal file

@ -0,0 +1,196 @@
# Developer Guide
Getting started with SecuBox-DEB development.
---
## Tech Stack
### Base System
- **OS**: Debian 12 (Bookworm) ARM64
- **Kernel**: 6.x with netfilter, tc, eBPF modules
- **Transport**: Tailscale (WireGuard-based mesh)
- **Containers**: Docker / Podman
### Security Stack
- **Firewall**: nftables (not iptables)
- **IDS/IPS**: Suricata + CrowdSec
- **WAF**: HAProxy + mitmproxy
- **DNS**: Unbound (Vortex DNS) + blocklists
- **DPI**: nDPId + netifyd (dual-stream via tc mirred)
- **Auth**: SecuBox-ZKP (Hamiltonian NP / GK-HAM-2025)
- **P2P Mesh**: MirrorNet (did:plc + WireGuard + Chain of Hamiltonians)
### Application Stack
- **Backend**: Python 3.11+ (FastAPI / Flask), Bash, C
- **Frontend**: HTML/CSS/JS vanilla or React
- **Config**: YAML + TOML, double-buffer / 4R versioning
- **Pipeline**: 5-stage production pipeline (collect → process → analyze → report → alert)
---
## Code Conventions
### Python
```python
"""
SecuBox-Deb :: <ModuleName>
CyberMind — https://cybermind.fr
Author: Gérald Kerma <gandalf@gk2.net>
License: Proprietary / ANSSI CSPN candidate
"""
from fastapi import APIRouter, Depends
from pydantic import BaseModel
router = APIRouter(prefix="/api/v1/module", tags=["module"])
class MetricsResponse(BaseModel):
cpu_percent: float
mem_percent: float
```
### Bash
```bash
#!/usr/bin/env bash
# SecuBox-Deb :: <script_name>
# CyberMind — Gérald Kerma
set -euo pipefail
readonly MODULE="<name>"
readonly VERSION="<semver>"
```
### nftables
```nft
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
log prefix "[SECUBOX-MODULE] " level info
}
}
```
---
## Double-Buffer / 4R Pattern
All configuration uses the PARAMETERS module with 4R versioning:
```
/etc/secubox/<module>/
├── active/ → live config (read-only in prod)
├── shadow/ → editable, validation before swap
├── rollback/ → 4 timestamped snapshots (R1..R4)
└── pending/ → awaiting ZKP validation
```
### Operations
```bash
# Swap double-buffer (atomic)
secubox-params swap --module <name> --validate-zkp
# Rollback to R1
secubox-params rollback --module <name> --target R1
# Check config status
secubox-params status --module <name>
```
---
## FastAPI Module Structure
```
packages/secubox-<module>/
├── api/
│ ├── __init__.py
│ ├── main.py ← FastAPI app with router
│ └── routers/
│ └── metrics.py ← Endpoint implementations
├── core/
│ ├── config.py ← TOML configuration
│ └── service.py ← Business logic
├── models/
│ └── schemas.py ← Pydantic models
├── www/
│ ├── index.html ← Web UI (from OpenWrt port)
│ └── static/
├── debian/
│ ├── control
│ ├── rules
│ ├── postinst
│ └── prerm
└── README.md
```
---
## Common Commands
```bash
# Build .deb package (cross-compile for ARM64)
cd packages/secubox-<module>
dpkg-buildpackage -a arm64 --host-arch arm64 -us -uc -b
# Deploy to device via SSH
bash scripts/deploy.sh secubox-<module> root@192.168.1.1
# Run API in development mode
uvicorn api.main:app --reload --uds /tmp/<module>.sock
# Run tests
pytest tests/ -v
# Check system status
systemctl status secubox-* --no-pager
# View live logs
journalctl -u secubox-* -f --output json | jq '.MESSAGE'
```
---
## ANSSI CSPN Compliance
1. **Privilege separation** by layer (L1/L2/L3)
2. **Encryption**: TLS 1.3 minimum
3. **Authentication**: ZKP Hamiltonian (GK-HAM-2025) — no plaintext secrets
4. **Logs**: Immutable, RFC 3339 timestamped, secure rotation
5. **Rollback**: Every config change → 4R snapshot mandatory
6. **Attack surface**: Minimal — disable unused services
7. **Tests**: Coverage ≥ 80%, regression tests on every PR
---
## What NOT to Do
- Use `iptables` (replaced by nftables)
- Use `uci` / LuCI (that's SecuBox-OpenWrt — abandoned)
- Write secrets in plaintext in code
- Use ACCEPT default firewall policies
- Suggest Python libraries with known vulnerabilities
- Ignore double-buffer schema for configs
- Mention "CrowdSec Ambassador" or "CyberMind Produits SASU"
---
## References
- [ANSSI CSPN](https://www.ssi.gouv.fr/entreprise/certification_cspn/)
- [nDPId](https://github.com/utoni/nDPId)
- [CrowdSec Docs](https://docs.crowdsec.net)
- [Suricata Docs](https://docs.suricata.io)
- [nftables Wiki](https://wiki.nftables.org)
---
*See also: [[Developer-Patterns]], [[Architecture-Boot]], [[Design-System]]*

790
Eye-Remote-Bootstrap-FR.md Normal file

@ -0,0 +1,790 @@
# Gestion des médias de démarrage Eye Remote Bootstrap
**Version:** 2.1.0
**Dernière mise à jour:** 2026-04-23
**Statut:** Production
**Auteur:** CyberMind — Gerald Kerma
---
## Présentation générale
Le système Eye Remote Bootstrap étend le gadget USB OTG du Pi Zero W pour fournir un canal de gestion de médias de démarrage pour les cartes ESPRESSObin. Via un seul câble USB OTG, l'Eye Remote fournit simultanément :
1. **Transport de métriques** (ECM) — Réseau Ethernet-sur-USB sur `10.55.0.0/30`
2. **Console série** (ACM) — Console de débogage sur `/dev/ttyACM0` (hôte) / `/dev/ttyGS0` (gadget)
3. **Média de démarrage** (Mass Storage) — LUN USB servant les images kernel, DTB, initrd et rootfs
Cela permet un workflow de récupération sans nécessiter d'intervention physique : flasher un nouveau noyau depuis le tableau de bord web de l'Eye Remote, le tester sur la carte cible, puis le promouvoir vers le slot actif avec une sémantique de swap atomique.
### Diagramme d'architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ Eye Remote Pi Zero W │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ FastAPI Router │───▶│ core/boot_media │───▶│ gadget-setup │ │
│ │ /boot-media/* │ │ (Python) │ │ (Bash) │ │
│ └────────┬────────┘ └────────┬─────────┘ └───────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ /var/lib/secubox/eye-remote/boot-media/ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌──────────────────────────────┐ │ │
│ │ │ active │ │ shadow │ │ images/<sha256>.img │ │ │
│ │ │ (link) │ │ (link) │ │ images/<sha256>.img.tmp (UP) │ │ │
│ │ └────┬────┘ └────┬────┘ └──────────────────────────────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────┐ ┌────────────────────┐ │ │
│ │ │ LUN 0 (mass_storage.usb0) │ │ tftp/ (symlinks) │ │ │
│ │ │ points to active slot │ │ serves shadow slot │ │ │
│ │ └─────────────────────────────┘ └────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ libcomposite configfs │ │
│ │ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │ │
│ │ │ ecm.usb0 │ │ acm.usb0 │ │ mass_storage.usb0 │ │ │
│ │ │ 10.55.0.2│ │ ttyGS0 │ │ LUN 0 (removable) │ │ │
│ │ └──────────┘ └──────────┘ └────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ USB OTG cable
┌─────────────────────────────────────────────────────────────────────┐
│ ESPRESSObin U-Boot │
│ Option 1: usb start → fatload usb 0 Image │
│ Option 2: dhcp → tftpboot $kernel_addr_r Image (shadow channel) │
└─────────────────────────────────────────────────────────────────────┘
```
### Structure du répertoire des médias de démarrage
L'Eye Remote maintient une structure de stockage à double buffer 4R :
```
/var/lib/secubox/eye-remote/boot-media/
├── state.json ← Métadonnées et état du média de démarrage
├── active ← Symlink → images/<sha256>.img
├── shadow ← Symlink → images/<sha256>.img (ou NULL)
├── images/
│ ├── a1b2c3d4e5f6.img ← Image FAT32 ou ext4 (lecture seule, dédupliquée)
│ ├── f0e1d2c3b4a5.img.tmp ← Upload en cours (temporaire)
│ ├── rollback-r1/ ← Active précédent (4R #1)
│ │ └── a1b2c3d4e5f6.img
│ ├── rollback-r2/ ← Active précédent (4R #2)
│ ├── rollback-r3/ ← Active précédent (4R #3)
│ └── rollback-r4/ ← Active précédent (4R #4)
└── tftp/ ← Racine du service TFTP (symlinks vers shadow)
├── Image → ../images/f0e1d2c3b4a5.img
├── device-tree.dtb
└── initrd.img
```
### Machine à états
```
État initial : Vide (pas d'active, pas de shadow)
┌─────────────────────────────────┐
│ UPLOAD SHADOW │
│ (via /api/v1/eye-remote/ │
│ boot-media/upload) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ SHADOW READY │
│ (image valide, extractible) │
│ │
│ [Branche A] Test via TFTP ──┐ │
│ (Optionnel) │ │
│ ▼ │
│ Test... │
│ │ │
│ [Branche B] ◄───────────────┘ │
│ Promouvoir Shadow vers Active │
│ (via /api/v1/eye-remote/ │
│ boot-media/swap) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ ACTIVE ONLY │
│ (shadow effacé, active défini) │
│ (LUN éjecté et rattaché) │
└────────────┬────────────────────┘
[Optionnel] │ Upload nouveau shadow
┌─────────────────────────────────┐
│ READY TO SWAP │
│ (active + shadow définis) │
│ Peut tester shadow ou rollback │
└────────────┬────────────────────┘
┌────────────┴───────────┐
│ │
│ Swap (promouvoir) │ Rollback (restaurer R1)
│ │
└────────────┬───────────┘
┌─────────────────────────────────┐
│ SWAPPED │
│ (shadow → active, active → R1) │
└─────────────────────────────────┘
```
---
## Fonctionnalités
### 1. LUN USB Mass Storage
- **Fonction:** `mass_storage.usb0` via libcomposite configfs
- **LUN 0:** Pointe vers le slot **active**
- **Média amovible:** Oui (permet l'éjection sans démontage)
- **Taille:** 16 MiB4 GiB (indépendant du système de fichiers)
- **Formats supportés:** FAT16, FAT32, ext2, ext3, ext4
- **Accès:** Lecture+Écriture (flashage environnement U-Boot, logs, etc.)
### 2. Double buffer avec rollback 4R
L'Eye Remote maintient **4 snapshots de rollback (4R)** :
- **Active:** Actuellement servi via LUN USB à l'ESPRESSObin
- **Shadow:** En attente de validation (uploadé mais non promu)
- **R1R4:** États actifs précédents, disponibles pour rollback
Chaque changement d'état (swap, rollback) est lié atomiquement et journalisé.
### 3. Canal shadow TFTP
En parallèle du LUN USB, l'Eye Remote exécute **dnsmasq TFTP** sur `10.55.0.2` port 69 :
- **Racine:** `/var/lib/secubox/eye-remote/boot-media/tftp/`
- **Contenu:** Symlinks vers le slot shadow (`Image`, `device-tree.dtb`, `initrd.img`)
- **Cas d'usage:** Tester un nouveau noyau sans swapper le slot actif
- **Commande de démarrage (ESPRESSObin U-Boot):**
```
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
```
### 4. Swap atomique résistant aux pannes
Lors de la promotion du shadow vers active :
1. **Éjecter LUN** du gadget (forcer la déconnexion)
2. **Swapper les symlinks atomiquement** (rename, pas unlink-puis-link)
3. **Mettre à jour les métadonnées** (state.json)
4. **Rattacher LUN** au gadget
5. **Vérifier** que le fichier LUN correspond au chemin attendu
Toutes les opérations protégées par **file lock + process lock** (style module PARAMETERS).
### 5. Gestion API
**Chemin de base:** `/api/v1/eye-remote/boot-media/`
Tous les endpoints nécessitent **l'authentification JWT** avec scope `boot:write` (pour POST) ou `boot:read` (pour GET).
---
## Endpoints API
| Méthode | Chemin | Authentification | Description |
|--------|------|------|---|
| **GET** | `/state` | `boot:read` | Récupérer l'état actuel du média de démarrage (slots, métadonnées) |
| **POST** | `/upload` | `boot:write` | Streamer une image vers le slot shadow (multipart chunked) |
| **POST** | `/swap` | `boot:write` | Promouvoir shadow vers active, rotation active → R1 |
| **POST** | `/rollback` | `boot:write` | Restaurer l'active précédent depuis R1R4 |
| **GET** | `/tftp/status` | `boot:read` | État du service TFTP et contenu shadow |
| **GET** | `/images` | `boot:read` | Lister les images disponibles avec métadonnées |
### Spécifications détaillées des endpoints
#### GET `/api/v1/eye-remote/boot-media/state`
**Requête:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state
```
**Réponse (200 OK):**
```json
{
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z",
"label": "debian-bookworm-arm64-espressobin"
},
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"lun_attached": true,
"last_swap_at": "2026-04-23T10:00:00Z",
"tftp_armed": true,
"rollback_available": ["r1", "r2", "r3"]
}
```
#### POST `/api/v1/eye-remote/boot-media/upload`
**Requête (multipart/form-data):**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64.img" \
-F "label=debian-bookworm-arm64-espressobin-rc1" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
**Paramètres:**
- `image` (fichier, requis): Image de démarrage (FAT32/ext4)
- `label` (chaîne, optionnel): Libellé lisible par l'humain
**Traitement:**
1. Streamer vers fichier temporaire avec suffixe `.tmp`
2. Calculer SHA256 pendant le streaming
3. Valider la magic du système de fichiers et la taille (16 MiB4 GiB)
4. Extraire les fichiers de démarrage vers `tftp/` (si extractible: Image, dtb, initrd)
5. Renommage atomique vers `images/<sha256>.img`
6. Mettre à jour le symlink shadow
**Réponse (201 Created):**
```json
{
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1",
"tftp_ready": true
}
```
**Réponse (400 Bad Request) — Image invalide:**
```json
{
"error": "Invalid filesystem",
"detail": "Image size must be 16 MiB4 GiB"
}
```
#### POST `/api/v1/eye-remote/boot-media/swap`
**Requête:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
```
**Paramètres optionnels:**
- `verify=true` (défaut): Vérifier que le LUN est rattaché avec succès
**Traitement:**
1. Vérifier que shadow existe et est valide
2. Éjecter LUN du gadget
3. Swapper les symlinks: `active``shadow`, `r1` ← ancien `active`
4. Décaler la chaîne de rollback: `r2``r1`, `r3``r2`, `r4``r3`
5. Effacer le slot shadow
6. Rattacher LUN
7. Mettre à jour state.json
**Réponse (200 OK):**
```json
{
"success": true,
"message": "Boot slot swapped successfully",
"active": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z"
},
"rollback_available": ["r1", "r2", "r3", "r4"]
}
```
**Réponse (409 Conflict) — Shadow non prêt:**
```json
{
"error": "No shadow to swap",
"detail": "Upload an image to shadow before promoting"
}
```
#### POST `/api/v1/eye-remote/boot-media/rollback`
**Requête:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
```
**Paramètres:**
- `target` (chaîne): Slot de rollback à restaurer (`r1`, `r2`, `r3`, ou `r4`)
**Traitement:**
1. Vérifier que la cible existe
2. Éjecter LUN
3. Promouvoir la cible vers active, rotation de la chaîne
4. Rattacher LUN
**Réponse (200 OK):**
```json
{
"success": true,
"message": "Restored from r1",
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z"
}
}
```
#### GET `/api/v1/eye-remote/boot-media/tftp/status`
**Requête:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status
```
**Réponse (200 OK):**
```json
{
"enabled": true,
"dnsmasq_running": true,
"port": 69,
"root": "/var/lib/secubox/eye-remote/boot-media/tftp",
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"files": [
{
"name": "Image",
"size": 12582912,
"type": "kernel"
},
{
"name": "device-tree.dtb",
"size": 65536,
"type": "devicetree"
},
{
"name": "initrd.img",
"size": 8388608,
"type": "initramfs"
}
]
}
```
---
## Exemples de workflow
### Workflow 1: Upload d'une nouvelle image
```bash
#!/bin/bash
# 1. Générer un token JWT (login en tant qu'utilisateur boot:write)
JWT=$(curl -s -X POST http://10.55.0.1:8000/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"boot-admin","password":"secubox-bootstrap"}' | jq -r .access_token)
# 2. Uploader nouvelle image vers shadow
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64-espressobin-rc1.img" \
-F "label=RC1 Build $(date +%Y%m%d)" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
# 3. Vérifier l'état actuel
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | jq .
# Sortie:
# {
# "active": { ... ancienne image ... },
# "shadow": { ... nouvelle image uploadée ... },
# "tftp_armed": true,
# ...
# }
```
### Workflow 2: Test via TFTP (Optionnel)
Aucun appel API nécessaire ! Le shadow est immédiatement disponible via TFTP.
```bash
# Sur la console U-Boot ESPRESSObin:
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
# Les logs de démarrage apparaissent sur la console série via Eye Remote
```
Si le noyau de test panique ou échoue, redémarrer simplement : U-Boot chargera le slot **active** depuis le LUN USB (inchangé).
### Workflow 3: Promouvoir Shadow vers Active
Une fois que le shadow est testé et stable :
```bash
# 1. Obtenir JWT (déjà disponible depuis upload)
JWT=$(...)
# 2. Promouvoir shadow vers active
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
# La réponse montre que active contient maintenant l'image RC1,
# l'ancien active est sauvegardé en r1, et shadow est effacé.
# 3. Redémarrer ESPRESSObin (ou cycle d'alimentation)
# U-Boot chargera maintenant le nouveau noyau depuis le LUN
```
### Workflow 4: Démarrage depuis LUN
Sur la console U-Boot ESPRESSObin :
```bash
=> usb start
=> usb tree
# Sortie:
# USB device tree:
# 1 Hub (480 Mb/s, 0mA)
# | ├─ 1.1 Mass Storage (active boot media)
# └─ ...
=> fatload usb 0 $kernel_addr_r Image
=> fatload usb 0 $fdt_addr_r device-tree.dtb
=> fatload usb 0 $initrd_addr_r initrd.img
=> booti $kernel_addr_r $initrd_addr_r:$initrd_size $fdt_addr_r
```
### Workflow 5: Rollback vers version précédente
Si l'image active devient corrompue ou instable :
```bash
# 1. Vérifier les points de rollback disponibles
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | \
jq .rollback_available
# Sortie: ["r1", "r2", "r3", "r4"]
# 2. Rollback vers r1 (précédent le plus récent)
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
# La réponse confirme que active est maintenant restauré depuis r1
# contenu r1 déplacé vers r2, r2→r3, r3→r4, r4 effacé
# 3. Redémarrer ESPRESSObin — démarre à nouveau l'ancien noyau
```
---
## Exigences des images
### Format
- **Supportés:** FAT16, FAT32, ext2, ext3, ext4
- **Recommandé:** FAT32 (compatibilité maximale U-Boot)
### Taille
- **Minimum:** 16 MiB (permet espace pour kernel + DTB + initrd)
- **Maximum:** 4 GiB (limite pratique du stockage de masse USB)
- **Typique:** 256 MiB1 GiB
### Contenu
**Requis (pour démarrage LUN USB):**
- Image du noyau (`Image` pour arm64, `zImage` pour arm32)
- Binaire device tree (`device-tree.dtb` ou `<board>.dtb`)
**Optionnel:**
- Disque RAM initial (`initrd.img`)
- Variables d'environnement U-Boot
- Script de démarrage
**Exemple de structure FAT32:**
```
/Image ← Noyau (requis)
/device-tree.dtb ← Device tree (requis)
/initrd.img ← Initramfs (optionnel)
/uEnv.txt ← Environnement U-Boot (optionnel)
/boot.scr ← Script de démarrage (optionnel)
```
### Validation
L'Eye Remote valide les images lors de l'upload :
1. **Magic système de fichiers:** Vérifier les octets magic pour FAT ou ext
2. **Vérification de taille:** Imposer limites 16 MiB4 GiB
3. **Extractibilité:** Pour TFTP, tenter d'extraire Image, dtb, initrd
4. **Digest SHA256:** Calculer et stocker pour suivi d'intégrité
Si la validation échoue, l'upload rejette avec 400 Bad Request.
---
## Configuration
### secubox.conf
L'Eye Remote bootstrap respecte les paramètres suivants dans `/etc/secubox/secubox.conf` :
```toml
[eye_remote]
enabled = true
bootstrap_enabled = true
bootstrap_root = "/var/lib/secubox/eye-remote/boot-media"
max_image_size_gb = 4
min_image_size_mb = 16
[eye_remote.tftp]
enabled = true
dnsmasq_config = "/etc/dnsmasq.d/secubox-eye-remote-tftp.conf"
port = 69
[eye_remote.gadget]
ecm_enabled = true
acm_enabled = true
mass_storage_enabled = true
```
### Configuration TFTP DHCP (dnsmasq)
**Fichier:** `/etc/dnsmasq.d/secubox-eye-remote-tftp.conf`
```ini
# Service TFTP pour bootstrap Eye Remote
enable-tftp
tftp-root=/var/lib/secubox/eye-remote/boot-media/tftp
tftp-port=69
listen-address=10.55.0.2
# Autoriser lecture depuis racine tftp uniquement (sécurité)
tftp-secure
# Augmenter timeout pour initrd volumineux
tftp-max-block-size=1024
```
### Ordre de mise sous tension
**Note:** Le gadget Eye Remote attache le LUN immédiatement au démarrage. L'U-Boot ESPRESSObin est responsable de détecter le LUN et d'initier `usb start`.
**Séquence recommandée:**
1. Mettre sous tension l'ESPRESSObin (U-Boot démarre, attend l'entrée utilisateur)
2. Brancher le câble USB OTG à l'Eye Remote
3. Attendre 2 secondes pour l'énumération USB
4. Appuyer sur Entrée sur U-Boot pour interrompre l'autoboot
5. Exécuter la commande `usb start`
6. Exécuter `fatload usb 0 ...` pour charger le noyau
---
## Dépannage
### Problème: "LUN non visible sur ESPRESSObin"
**Symptômes:**
- `usb start` n'affiche aucun périphérique de stockage de masse
- `usb tree` liste uniquement le hub, pas de LUN
**Diagnostic:**
```bash
# Sur Eye Remote (hôte):
ssh pi@eye-remote.local
systemctl status secubox-eye-remote-gadget
# Vérifier si l'arbre gadget existe:
ls -la /sys/kernel/config/usb_gadget/secubox/functions/mass_storage.usb0/
```
**Solutions:**
1. **Redémarrer le gadget:**
```bash
systemctl restart secubox-eye-remote-gadget
```
2. **Vérifier que le symlink active existe:**
```bash
ls -la /var/lib/secubox/eye-remote/boot-media/active
# Doit pointer vers un fichier image réel
```
3. **Vérifier que le fichier est lisible:**
```bash
ls -lah /var/lib/secubox/eye-remote/boot-media/images/
# Les fichiers doivent avoir les permissions de lecture
```
4. **Vérifier physiquement la connexion USB:**
- Utiliser le port DATA (milieu), pas le port PWR
- Essayer un câble USB ou port différent
- Vérifier qu'il n'y a pas de hub USB entre Eye Remote et ESPRESSObin
### Problème: "Timeout TFTP / Image non trouvée"
**Symptômes:**
- `tftpboot` se bloque ou signale "not found"
- Chemin racine TFTP incorrect
**Diagnostic:**
```bash
# Vérifier le service TFTP:
curl http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status | jq .
# Vérifier le symlink shadow:
ls -la /var/lib/secubox/eye-remote/boot-media/tftp/
# Vérifier que dnsmasq TFTP est en cours d'exécution:
ps aux | grep dnsmasq
netstat -tlnup | grep :69
```
**Solutions:**
1. **Uploader d'abord une image vers shadow:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm.img" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
2. **Vérifier la connectivité réseau:**
```bash
# Sur ESPRESSObin U-Boot:
=> ping 10.55.0.2
# Devrait répondre avec l'IP de l'hôte
```
3. **Vérifier que l'extraction de fichier a réussi:**
- L'état TFTP devrait montrer un tableau `files` non vide
- Si l'image est brute (pas de système de fichiers), l'extraction doit échouer gracieusement
- Utiliser le démarrage LUN à la place
### Problème: "Échec du swap / Timeout d'éjection LUN"
**Symptômes:**
- `POST /swap` retourne une erreur 500
- LUN reste bloqué dans le gadget
**Diagnostic:**
```bash
# Vérifier le verrou gadget:
lsof | grep /var/lib/secubox/eye-remote/boot-media/
# Vérifier le log gadget-setup.sh:
journalctl -u secubox-eye-remote-gadget -n 50
# Vérifier que le verrou fichier n'est pas tenu:
ps aux | grep eye-remote
```
**Solutions:**
1. **Forcer l'éjection via shell (attention !):**
```bash
sudo /usr/sbin/gadget-setup.sh swap-lun ""
sleep 0.5
sudo /usr/sbin/gadget-setup.sh swap-lun \
"/var/lib/secubox/eye-remote/boot-media/active"
```
2. **Redémarrer le service gadget:**
```bash
systemctl stop secubox-eye-remote-gadget
sleep 2
systemctl start secubox-eye-remote-gadget
```
3. **Vérifier les processus obsolètes:**
```bash
systemctl status secubox-eye-remote-api
# Si le processus API détient le verrou, le redémarrer
systemctl restart secubox-eye-remote-api
```
### Problème: "Système de fichiers invalide lors de l'upload"
**Symptômes:**
- `POST /upload` retourne 400 Bad Request
- Erreur: "Invalid filesystem" ou "Size out of range"
**Solutions:**
1. **Vérifier le format de l'image:**
```bash
file debian-bookworm.img
# Devrait afficher: FAT boot sector, x86 or x64 boot loader binary
# ou: Linux rev 1.0 ext4 filesystem
```
2. **Vérifier la taille de l'image:**
```bash
ls -lh debian-bookworm.img
# Devrait être entre 16 MiB et 4 GiB
```
3. **Créer une image FAT32 valide si nécessaire:**
```bash
# Créer une image FAT32 de 256 MiB
fallocate -l 256M debian-bookworm.img
mkfs.vfat -F32 debian-bookworm.img
# Monter et copier les fichiers du noyau
sudo mount debian-bookworm.img /mnt/boot
sudo cp Image /mnt/boot/
sudo cp device-tree.dtb /mnt/boot/
sudo umount /mnt/boot
```
---
## Voir aussi
- **[Eye Remote Hardware](Eye-Remote-Hardware.md)** — Connexions physiques, affectation des broches
- **[Eye Remote Gateway](Eye-Remote-Gateway.md)** — Configuration réseau, DHCP/DNS
- **[Eye Remote Implementation](Eye-Remote-Implementation.md)** — Internals Python/Bash, structure du codebase
- **[Architecture Boot](Architecture-Boot.md)** — Architecture de démarrage globale pour SecuBox-Deb
- **[U-Boot Documentation](../eye-remote/uboot-bootcmd.md)** — Commandes U-Boot ESPRESSObin
---
**CyberMind · SecuBox-Deb · Eye Remote Bootstrap v2.1.0**
*Dernière révision: 2026-04-23 · Mainteneur: Gerald Kerma <gandalf@cybermind.fr>*

790
Eye-Remote-Bootstrap-ZH.md Normal file

@ -0,0 +1,790 @@
# Eye Remote Bootstrap 启动媒体管理
**版本:** 2.1.0
**最后更新:** 2026-04-23
**状态:** 生产环境
**作者:** CyberMind — Gerald Kerma
---
## 概述
Eye Remote Bootstrap 系统扩展了 Pi Zero W USB OTG 小工具,为 ESPRESSObin 板提供托管启动媒体通道。通过单个 USB OTG 电缆Eye Remote 同时提供:
1. **指标传输** (ECM) — 10.55.0.0/30 上的 USB 以太网网络
2. **串行控制台** (ACM) — /dev/ttyACM0主机/ /dev/ttyGS0小工具上的调试控制台
3. **启动媒体** (Mass Storage) — 提供内核、DTB、initrd 和 rootfs 镜像的 USB LUN
这使得恢复工作流程无需物理干预:从 Eye Remote Web 仪表板刷写新内核,在目标板上测试它,然后使用原子交换语义将其提升到活动槽。
### 架构图
```
┌─────────────────────────────────────────────────────────────────────┐
│ Eye Remote Pi Zero W │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ FastAPI Router │───▶│ core/boot_media │───▶│ gadget-setup │ │
│ │ /boot-media/* │ │ (Python) │ │ (Bash) │ │
│ └────────┬────────┘ └────────┬─────────┘ └───────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ /var/lib/secubox/eye-remote/boot-media/ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌──────────────────────────────┐ │ │
│ │ │ active │ │ shadow │ │ images/<sha256>.img │ │ │
│ │ │ (link) │ │ (link) │ │ images/<sha256>.img.tmp (UP) │ │ │
│ │ └────┬────┘ └────┬────┘ └──────────────────────────────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────┐ ┌────────────────────┐ │ │
│ │ │ LUN 0 (mass_storage.usb0) │ │ tftp/ (symlinks) │ │ │
│ │ │ points to active slot │ │ serves shadow slot │ │ │
│ │ └─────────────────────────────┘ └────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ libcomposite configfs │ │
│ │ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │ │
│ │ │ ecm.usb0 │ │ acm.usb0 │ │ mass_storage.usb0 │ │ │
│ │ │ 10.55.0.2│ │ ttyGS0 │ │ LUN 0 (removable) │ │ │
│ │ └──────────┘ └──────────┘ └────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ USB OTG cable
┌─────────────────────────────────────────────────────────────────────┐
│ ESPRESSObin U-Boot │
│ Option 1: usb start → fatload usb 0 Image │
│ Option 2: dhcp → tftpboot $kernel_addr_r Image (shadow channel) │
└─────────────────────────────────────────────────────────────────────┘
```
### 启动媒体目录结构
Eye Remote 维护双缓冲 4R 存储布局:
```
/var/lib/secubox/eye-remote/boot-media/
├── state.json ← 启动媒体元数据和状态
├── active ← 符号链接 → images/<sha256>.img
├── shadow ← 符号链接 → images/<sha256>.img或 NULL
├── images/
│ ├── a1b2c3d4e5f6.img ← FAT32 或 ext4 镜像(只读,去重)
│ ├── f0e1d2c3b4a5.img.tmp ← 上传进行中(临时)
│ ├── rollback-r1/ ← 先前活动4R #1
│ │ └── a1b2c3d4e5f6.img
│ ├── rollback-r2/ ← 先前活动4R #2
│ ├── rollback-r3/ ← 先前活动4R #3
│ └── rollback-r4/ ← 先前活动4R #4
└── tftp/ ← TFTP 服务根目录(指向 shadow 的符号链接)
├── Image → ../images/f0e1d2c3b4a5.img
├── device-tree.dtb
└── initrd.img
```
### 状态机
```
初始状态:空(无 active无 shadow
┌─────────────────────────────────┐
│ UPLOAD SHADOW │
│ (通过 /api/v1/eye-remote/ │
│ boot-media/upload) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ SHADOW READY │
│ (镜像有效,可提取) │
│ │
│ [分支 A] 通过 TFTP 测试 ──┐ │
│ (可选) │ │
│ ▼ │
│ 测试中... │
│ │ │
│ [分支 B] ◄───────────────┘ │
│ 将 Shadow 提升为 Active │
│ (通过 /api/v1/eye-remote/ │
│ boot-media/swap) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ ACTIVE ONLY │
│ (shadow 已清除active 已设置) │
│ (LUN 已弹出并重新附加) │
└────────────┬────────────────────┘
[可选] │ 上传新 shadow
┌─────────────────────────────────┐
│ READY TO SWAP │
│ (active + shadow 均已设置) │
│ 可以测试 shadow 或回滚 │
└────────────┬────────────────────┘
┌────────────┴───────────┐
│ │
│ Swap提升 shadow │ Rollback恢复 R1
│ │
└────────────┬───────────┘
┌─────────────────────────────────┐
│ SWAPPED │
│ (shadow → active, active → R1) │
└─────────────────────────────────┘
```
---
## 功能特性
### 1. USB Mass Storage LUN
- **功能:** 通过 libcomposite configfs 的 `mass_storage.usb0`
- **LUN 0:** 指向 **active** 启动槽
- **可移动媒体:** 是(允许弹出而无需卸载)
- **大小:** 16 MiB4 GiB文件系统无关
- **支持格式:** FAT16、FAT32、ext2、ext3、ext4
- **访问:** 读+写(刷写 U-Boot 环境、日志等)
### 2. 双缓冲与 4R 回滚
Eye Remote 维护 **4 个回滚快照4R**
- **Active:** 当前通过 USB LUN 向 ESPRESSObin 提供服务
- **Shadow:** 待验证(已上传但未提升)
- **R1R4:** 先前的活动状态,可用于回滚
每次状态更改(交换、回滚)都会原子链接并记录。
### 3. TFTP Shadow 通道
与 USB LUN 并行Eye Remote 在 10.55.0.2 端口 69 上运行 **dnsmasq TFTP**
- **根目录:** `/var/lib/secubox/eye-remote/boot-media/tftp/`
- **内容:** 指向 shadow 槽的符号链接(`Image`、`device-tree.dtb`、`initrd.img`
- **使用场景:** 测试新内核而不交换活动槽
- **启动命令ESPRESSObin U-Boot:**
```
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
```
### 4. 防崩溃原子交换
提升 shadow 到 active 时:
1. **从小工具弹出 LUN**(强制断开连接)
2. **原子交换符号链接**(重命名,而不是取消链接然后链接)
3. **更新元数据**state.json
4. **重新附加 LUN** 到小工具
5. **验证** LUN 文件与预期路径匹配
所有操作都受 **文件锁 + 进程锁**PARAMETERS 模块样式)保护。
### 5. API 管理
**基本路径:** `/api/v1/eye-remote/boot-media/`
所有端点都需要 **JWT 身份验证**POST 需要 `boot:write` 范围GET 需要 `boot:read` 范围。
---
## API 端点
| 方法 | 路径 | 身份验证 | 描述 |
|--------|------|------|---|
| **GET** | `/state` | `boot:read` | 获取当前启动媒体状态(槽、元数据) |
| **POST** | `/upload` | `boot:write` | 流式传输镜像到 shadow 槽(分块 multipart |
| **POST** | `/swap` | `boot:write` | 将 shadow 提升为 activeactive 轮换到 R1 |
| **POST** | `/rollback` | `boot:write` | 从 R1R4 恢复先前的 active |
| **GET** | `/tftp/status` | `boot:read` | TFTP 服务状态和 shadow 内容 |
| **GET** | `/images` | `boot:read` | 列出可用镜像及元数据 |
### 端点详细规范
#### GET `/api/v1/eye-remote/boot-media/state`
**请求:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state
```
**响应 (200 OK):**
```json
{
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z",
"label": "debian-bookworm-arm64-espressobin"
},
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"lun_attached": true,
"last_swap_at": "2026-04-23T10:00:00Z",
"tftp_armed": true,
"rollback_available": ["r1", "r2", "r3"]
}
```
#### POST `/api/v1/eye-remote/boot-media/upload`
**请求 (multipart/form-data):**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64.img" \
-F "label=debian-bookworm-arm64-espressobin-rc1" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
**参数:**
- `image`文件必需启动镜像FAT32/ext4
- `label`(字符串,可选):人类可读标签
**处理:**
1. 流式传输到带 `.tmp` 后缀的临时文件
2. 在流式传输期间计算 SHA256
3. 验证文件系统魔数和大小16 MiB4 GiB
4. 提取启动文件到 `tftp/`如果可提取Image、dtb、initrd
5. 原子重命名为 `images/<sha256>.img`
6. 更新 shadow 符号链接
**响应 (201 Created):**
```json
{
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1",
"tftp_ready": true
}
```
**响应 (400 Bad Request) — 镜像无效:**
```json
{
"error": "Invalid filesystem",
"detail": "Image size must be 16 MiB4 GiB"
}
```
#### POST `/api/v1/eye-remote/boot-media/swap`
**请求:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
```
**可选参数:**
- `verify=true`(默认):验证 LUN 重新附加成功
**处理:**
1. 检查 shadow 存在且有效
2. 从小工具弹出 LUN
3. 交换符号链接:`active` ← `shadow``r1` ← 旧 `active`
4. 移动回滚链:`r2` ← `r1``r3` ← `r2``r4` ← `r3`
5. 清除 shadow 槽
6. 重新附加 LUN
7. 更新 state.json
**响应 (200 OK):**
```json
{
"success": true,
"message": "Boot slot swapped successfully",
"active": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z"
},
"rollback_available": ["r1", "r2", "r3", "r4"]
}
```
**响应 (409 Conflict) — Shadow 未准备好:**
```json
{
"error": "No shadow to swap",
"detail": "Upload an image to shadow before promoting"
}
```
#### POST `/api/v1/eye-remote/boot-media/rollback`
**请求:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
```
**参数:**
- `target`(字符串):要恢复的回滚槽(`r1`、`r2`、`r3` 或 `r4`
**处理:**
1. 检查目标存在
2. 弹出 LUN
3. 将目标提升为 active轮换链
4. 重新附加 LUN
**响应 (200 OK):**
```json
{
"success": true,
"message": "Restored from r1",
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z"
}
}
```
#### GET `/api/v1/eye-remote/boot-media/tftp/status`
**请求:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status
```
**响应 (200 OK):**
```json
{
"enabled": true,
"dnsmasq_running": true,
"port": 69,
"root": "/var/lib/secubox/eye-remote/boot-media/tftp",
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"files": [
{
"name": "Image",
"size": 12582912,
"type": "kernel"
},
{
"name": "device-tree.dtb",
"size": 65536,
"type": "devicetree"
},
{
"name": "initrd.img",
"size": 8388608,
"type": "initramfs"
}
]
}
```
---
## 工作流程示例
### 工作流程 1上传新镜像
```bash
#!/bin/bash
# 1. 生成 JWT token以 boot:write 用户身份登录)
JWT=$(curl -s -X POST http://10.55.0.1:8000/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"boot-admin","password":"secubox-bootstrap"}' | jq -r .access_token)
# 2. 上传新镜像到 shadow
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64-espressobin-rc1.img" \
-F "label=RC1 Build $(date +%Y%m%d)" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
# 3. 检查当前状态
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | jq .
# 输出:
# {
# "active": { ... 旧镜像 ... },
# "shadow": { ... 刚上传的新镜像 ... },
# "tftp_armed": true,
# ...
# }
```
### 工作流程 2通过 TFTP 测试(可选)
无需 API 调用shadow 立即通过 TFTP 可用。
```bash
# 在 ESPRESSObin U-Boot 控制台上:
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
# 启动日志通过 Eye Remote 显示在串行控制台上
```
如果测试内核崩溃或失败只需重新启动U-Boot 将从 USB LUN 加载 **active** 槽(未更改)。
### 工作流程 3将 Shadow 提升为 Active
一旦 shadow 经过测试且稳定:
```bash
# 1. 获取 JWT已从上传获得
JWT=$(...)
# 2. 将 shadow 提升为 active
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
# 响应显示 active 现在包含 RC1 镜像,
# 旧 active 保存在 r1 中shadow 已清除。
# 3. 重启 ESPRESSObin或电源循环
# U-Boot 现在将从 LUN 加载新内核
```
### 工作流程 4从 LUN 启动
在 ESPRESSObin U-Boot 控制台上:
```bash
=> usb start
=> usb tree
# 输出:
# USB device tree:
# 1 Hub (480 Mb/s, 0mA)
# | ├─ 1.1 Mass Storage (active boot media)
# └─ ...
=> fatload usb 0 $kernel_addr_r Image
=> fatload usb 0 $fdt_addr_r device-tree.dtb
=> fatload usb 0 $initrd_addr_r initrd.img
=> booti $kernel_addr_r $initrd_addr_r:$initrd_size $fdt_addr_r
```
### 工作流程 5回滚到先前版本
如果活动镜像损坏或不稳定:
```bash
# 1. 检查可用的回滚点
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | \
jq .rollback_available
# 输出: ["r1", "r2", "r3", "r4"]
# 2. 回滚到 r1最近的先前版本
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
# 响应确认 active 现已从 r1 恢复
# r1 内容移至 r2r2→r3r3→r4r4 清除
# 3. 重启 ESPRESSObin — 再次启动旧内核
```
---
## 镜像要求
### 格式
- **支持:** FAT16、FAT32、ext2、ext3、ext4
- **推荐:** FAT32最大 U-Boot 兼容性)
### 大小
- **最小:** 16 MiB允许内核 + DTB + initrd 的空间)
- **最大:** 4 GiBUSB 大容量存储实际限制)
- **典型:** 256 MiB1 GiB
### 内容
**必需(用于 USB LUN 启动):**
- 内核镜像arm64 为 `Image`arm32 为 `zImage`
- 设备树二进制文件(`device-tree.dtb` 或 `<board>.dtb`
**可选:**
- 初始 ramdisk`initrd.img`
- U-Boot 环境变量
- 启动脚本
**FAT32 结构示例:**
```
/Image ← 内核(必需)
/device-tree.dtb ← 设备树(必需)
/initrd.img ← Initramfs可选
/uEnv.txt ← U-Boot 环境(可选)
/boot.scr ← 启动脚本(可选)
```
### 验证
Eye Remote 在上传时验证镜像:
1. **文件系统魔数:** 检查 FAT 或 ext 的魔数字节
2. **大小检查:** 强制执行 16 MiB4 GiB 边界
3. **可提取性:** 对于 TFTP尝试提取 Image、dtb、initrd
4. **SHA256 摘要:** 计算并存储以进行完整性跟踪
如果验证失败,上传将以 400 Bad Request 拒绝。
---
## 配置
### secubox.conf
Eye Remote bootstrap 遵循 `/etc/secubox/secubox.conf` 中的以下设置:
```toml
[eye_remote]
enabled = true
bootstrap_enabled = true
bootstrap_root = "/var/lib/secubox/eye-remote/boot-media"
max_image_size_gb = 4
min_image_size_mb = 16
[eye_remote.tftp]
enabled = true
dnsmasq_config = "/etc/dnsmasq.d/secubox-eye-remote-tftp.conf"
port = 69
[eye_remote.gadget]
ecm_enabled = true
acm_enabled = true
mass_storage_enabled = true
```
### TFTP DHCP 配置 (dnsmasq)
**文件:** `/etc/dnsmasq.d/secubox-eye-remote-tftp.conf`
```ini
# TFTP service for Eye Remote bootstrap
enable-tftp
tftp-root=/var/lib/secubox/eye-remote/boot-media/tftp
tftp-port=69
listen-address=10.55.0.2
# Allow read from tftp root only (security)
tftp-secure
# Increase timeout for large initrd
tftp-max-block-size=1024
```
### 上电顺序
**注意:** Eye Remote 小工具在启动时立即附加 LUN。ESPRESSObin U-Boot 负责检测 LUN 并启动 `usb start`
**推荐序列:**
1. 给 ESPRESSObin 上电U-Boot 启动,等待用户输入)
2. 将 USB OTG 电缆插入 Eye Remote
3. 等待 2 秒进行 USB 枚举
4. 在 U-Boot 上按 Enter 中断自动启动
5. 执行 `usb start` 命令
6. 执行 `fatload usb 0 ...` 加载内核
---
## 故障排除
### 问题:"ESPRESSObin 上 LUN 不可见"
**症状:**
- `usb start` 不显示大容量存储设备
- `usb tree` 仅列出集线器,无 LUN
**诊断:**
```bash
# 在 Eye Remote主机上:
ssh pi@eye-remote.local
systemctl status secubox-eye-remote-gadget
# 检查小工具树是否存在:
ls -la /sys/kernel/config/usb_gadget/secubox/functions/mass_storage.usb0/
```
**解决方案:**
1. **重启小工具:**
```bash
systemctl restart secubox-eye-remote-gadget
```
2. **检查 active 符号链接存在:**
```bash
ls -la /var/lib/secubox/eye-remote/boot-media/active
# 应指向真实镜像文件
```
3. **验证文件可读:**
```bash
ls -lah /var/lib/secubox/eye-remote/boot-media/images/
# 文件应具有读取权限
```
4. **物理检查 USB 连接:**
- 使用 DATA 端口(中间),而不是 PWR 端口
- 尝试不同的 USB 电缆或端口
- 验证 Eye Remote 和 ESPRESSObin 之间没有 USB 集线器
### 问题:"TFTP 超时 / 未找到镜像"
**症状:**
- `tftpboot` 挂起或报告 "not found"
- TFTP 根路径不正确
**诊断:**
```bash
# 检查 TFTP 服务:
curl http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status | jq .
# 检查 shadow 符号链接:
ls -la /var/lib/secubox/eye-remote/boot-media/tftp/
# 验证 dnsmasq TFTP 正在运行:
ps aux | grep dnsmasq
netstat -tlnup | grep :69
```
**解决方案:**
1. **首先上传镜像到 shadow:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm.img" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
2. **验证网络连接:**
```bash
# 在 ESPRESSObin U-Boot 上:
=> ping 10.55.0.2
# 应使用主机 IP 响应
```
3. **检查文件提取是否成功:**
- TFTP 状态应显示非空 `files` 数组
- 如果镜像是原始的(无文件系统),提取必须优雅失败
- 改为使用 LUN 启动
### 问题:"交换失败 / LUN 弹出超时"
**症状:**
- `POST /swap` 返回 500 错误
- LUN 在小工具中卡住
**诊断:**
```bash
# 检查小工具锁:
lsof | grep /var/lib/secubox/eye-remote/boot-media/
# 检查 gadget-setup.sh 日志:
journalctl -u secubox-eye-remote-gadget -n 50
# 验证文件锁未被持有:
ps aux | grep eye-remote
```
**解决方案:**
1. **通过 shell 强制弹出(小心!):**
```bash
sudo /usr/sbin/gadget-setup.sh swap-lun ""
sleep 0.5
sudo /usr/sbin/gadget-setup.sh swap-lun \
"/var/lib/secubox/eye-remote/boot-media/active"
```
2. **重启小工具服务:**
```bash
systemctl stop secubox-eye-remote-gadget
sleep 2
systemctl start secubox-eye-remote-gadget
```
3. **检查过时进程:**
```bash
systemctl status secubox-eye-remote-api
# 如果 API 进程持有锁,重启它
systemctl restart secubox-eye-remote-api
```
### 问题:"上传时文件系统无效"
**症状:**
- `POST /upload` 返回 400 Bad Request
- 错误:"Invalid filesystem" 或 "Size out of range"
**解决方案:**
1. **验证镜像格式:**
```bash
file debian-bookworm.img
# 应输出: FAT boot sector, x86 or x64 boot loader binary
# 或: Linux rev 1.0 ext4 filesystem
```
2. **检查镜像大小:**
```bash
ls -lh debian-bookworm.img
# 应在 16 MiB 到 4 GiB 之间
```
3. **如果需要,创建有效的 FAT32 镜像:**
```bash
# 创建 256 MiB FAT32 镜像
fallocate -l 256M debian-bookworm.img
mkfs.vfat -F32 debian-bookworm.img
# 挂载并复制内核文件
sudo mount debian-bookworm.img /mnt/boot
sudo cp Image /mnt/boot/
sudo cp device-tree.dtb /mnt/boot/
sudo umount /mnt/boot
```
---
## 另请参阅
- **[Eye Remote Hardware](Eye-Remote-Hardware.md)** — 物理连接,引脚分配
- **[Eye Remote Gateway](Eye-Remote-Gateway.md)** — 网络配置DHCP/DNS
- **[Eye Remote Implementation](Eye-Remote-Implementation.md)** — Python/Bash 内部,代码库结构
- **[Architecture Boot](Architecture-Boot.md)** — SecuBox-Deb 的整体启动架构
- **[U-Boot Documentation](../eye-remote/uboot-bootcmd.md)** — ESPRESSObin U-Boot 命令
---
**CyberMind · SecuBox-Deb · Eye Remote Bootstrap v2.1.0**
*最后审查: 2026-04-23 · 维护者: Gerald Kerma <gandalf@cybermind.fr>*

792
Eye-Remote-Bootstrap.md Normal file

@ -0,0 +1,792 @@
# Eye Remote Bootstrap Media Management
**Version:** 2.1.1
**Last Updated:** 2026-04-24
**Status:** Production
**Author:** CyberMind — Gerald Kerma
> **v2.1.1 Fix:** USB OTG network now uses `usb1` (ECM) instead of `usb0` (RNDIS) for Linux host compatibility. This fixes the NO-CARRIER issue where the host couldn't establish network connectivity despite the Pi Zero interface being UP.
---
## Overview
The Eye Remote Bootstrap system extends the Pi Zero W USB OTG gadget to provide a managed boot media channel for ESPRESSObin boards. Via a single USB OTG cable, the Eye Remote simultaneously provides:
1. **Metrics Transport** (ECM) — Ethernet-over-USB network on `10.55.0.0/30`
2. **Serial Console** (ACM) — Debug console on `/dev/ttyACM0` (host) / `/dev/ttyGS0` (gadget)
3. **Boot Media** (Mass Storage) — USB LUN serving kernel, DTB, initrd, and rootfs images
This enables a recovery workflow without requiring physical intervention: flash a new kernel from the Eye Remote web dashboard, test it on the target board, then promote it to the active slot with atomic swap semantics.
### Architecture Diagram
```
┌─────────────────────────────────────────────────────────────────────┐
│ Eye Remote Pi Zero W │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ FastAPI Router │───▶│ core/boot_media │───▶│ gadget-setup │ │
│ │ /boot-media/* │ │ (Python) │ │ (Bash) │ │
│ └────────┬────────┘ └────────┬─────────┘ └───────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ /var/lib/secubox/eye-remote/boot-media/ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌──────────────────────────────┐ │ │
│ │ │ active │ │ shadow │ │ images/<sha256>.img │ │ │
│ │ │ (link) │ │ (link) │ │ images/<sha256>.img.tmp (UP) │ │ │
│ │ └────┬────┘ └────┬────┘ └──────────────────────────────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────┐ ┌────────────────────┐ │ │
│ │ │ LUN 0 (mass_storage.usb0) │ │ tftp/ (symlinks) │ │ │
│ │ │ points to active slot │ │ serves shadow slot │ │ │
│ │ └─────────────────────────────┘ └────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ libcomposite configfs │ │
│ │ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │ │
│ │ │ ecm.usb0 │ │ acm.usb0 │ │ mass_storage.usb0 │ │ │
│ │ │ 10.55.0.2│ │ ttyGS0 │ │ LUN 0 (removable) │ │ │
│ │ └──────────┘ └──────────┘ └────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ USB OTG cable
┌─────────────────────────────────────────────────────────────────────┐
│ ESPRESSObin U-Boot │
│ Option 1: usb start → fatload usb 0 Image │
│ Option 2: dhcp → tftpboot $kernel_addr_r Image (shadow channel) │
└─────────────────────────────────────────────────────────────────────┘
```
### Boot Media Directory Structure
The Eye Remote maintains a double-buffer 4R storage layout:
```
/var/lib/secubox/eye-remote/boot-media/
├── state.json ← Boot media metadata & state
├── active ← Symlink → images/<sha256>.img
├── shadow ← Symlink → images/<sha256>.img (or NULL)
├── images/
│ ├── a1b2c3d4e5f6.img ← FAT32 or ext4 image (read-only, deduplicated)
│ ├── f0e1d2c3b4a5.img.tmp ← Upload in progress (temporary)
│ ├── rollback-r1/ ← Previous active (4R #1)
│ │ └── a1b2c3d4e5f6.img
│ ├── rollback-r2/ ← Previous active (4R #2)
│ ├── rollback-r3/ ← Previous active (4R #3)
│ └── rollback-r4/ ← Previous active (4R #4)
└── tftp/ ← TFTP service root (symlinks to shadow)
├── Image → ../images/f0e1d2c3b4a5.img
├── device-tree.dtb
└── initrd.img
```
### State Machine
```
Initial State: Empty (no active, no shadow)
┌─────────────────────────────────┐
│ UPLOAD SHADOW │
│ (via /api/v1/eye-remote/ │
│ boot-media/upload) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ SHADOW READY │
│ (image valid, extractable) │
│ │
│ [Branch A] Test via TFTP ──┐ │
│ (Optional) │ │
│ ▼ │
│ Testing... │
│ │ │
│ [Branch B] ◄───────────────┘ │
│ Promote Shadow to Active │
│ (via /api/v1/eye-remote/ │
│ boot-media/swap) │
└────────────┬────────────────────┘
┌─────────────────────────────────┐
│ ACTIVE ONLY │
│ (shadow cleared, active set) │
│ (LUN ejected & reattached) │
└────────────┬────────────────────┘
[Optional] │ Upload new shadow
┌─────────────────────────────────┐
│ READY TO SWAP │
│ (active + shadow both set) │
│ Can test shadow or rollback │
└────────────┬────────────────────┘
┌────────────┴───────────┐
│ │
│ Swap (promote shadow) │ Rollback (restore R1)
│ │
└────────────┬───────────┘
┌─────────────────────────────────┐
│ SWAPPED │
│ (shadow → active, active → R1) │
└─────────────────────────────────┘
```
---
## Features
### 1. USB Mass Storage LUN
- **Function:** `mass_storage.usb0` via libcomposite configfs
- **LUN 0:** Points to the **active** boot slot
- **Removable Media:** Yes (allows eject without unmount)
- **Size:** 16 MiB4 GiB (filesystem-agnostic)
- **Formats Supported:** FAT16, FAT32, ext2, ext3, ext4
- **Access:** Read+Write (flashing U-Boot environment, logs, etc.)
### 2. Double-Buffer with 4R Rollback
The Eye Remote maintains **4 rollback snapshots (4R)**:
- **Active:** Currently served via USB LUN to ESPRESSObin
- **Shadow:** Pending validation (uploaded but not promoted)
- **R1R4:** Previous active states, available for rollback
Each state change (swap, rollback) is atomically linked and logged.
### 3. TFTP Shadow Channel
In parallel with the USB LUN, the Eye Remote runs **dnsmasq TFTP** on `10.55.0.2` port 69:
- **Root:** `/var/lib/secubox/eye-remote/boot-media/tftp/`
- **Content:** Symlinks to shadow slot (`Image`, `device-tree.dtb`, `initrd.img`)
- **Use Case:** Test new kernel without swapping active slot
- **Boot Command (ESPRESSObin U-Boot):**
```
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
```
### 4. Crash-Safe Atomic Swap
When promoting shadow to active:
1. **Eject LUN** from gadget (force disconnect)
2. **Swap symlinks atomically** (rename, not unlink-then-link)
3. **Update metadata** (state.json)
4. **Re-attach LUN** to gadget
5. **Verify** LUN file matches expected path
All operations protected by **file lock + process lock** (PARAMETERS module style).
### 5. API Management
**Base Path:** `/api/v1/eye-remote/boot-media/`
All endpoints require **JWT authentication** with scope `boot:write` (for POST) or `boot:read` (for GET).
---
## API Endpoints
| Method | Path | Authentication | Description |
|--------|------|------|---|
| **GET** | `/state` | `boot:read` | Fetch current boot media state (slots, metadata) |
| **POST** | `/upload` | `boot:write` | Stream image to shadow slot (chunked multipart) |
| **POST** | `/swap` | `boot:write` | Promote shadow to active, rotate active → R1 |
| **POST** | `/rollback` | `boot:write` | Restore previous active from R1R4 |
| **GET** | `/tftp/status` | `boot:read` | TFTP service status & shadow contents |
| **GET** | `/images` | `boot:read` | List available images with metadata |
### Detailed Endpoint Specifications
#### GET `/api/v1/eye-remote/boot-media/state`
**Request:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state
```
**Response (200 OK):**
```json
{
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z",
"label": "debian-bookworm-arm64-espressobin"
},
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"lun_attached": true,
"last_swap_at": "2026-04-23T10:00:00Z",
"tftp_armed": true,
"rollback_available": ["r1", "r2", "r3"]
}
```
#### POST `/api/v1/eye-remote/boot-media/upload`
**Request (multipart/form-data):**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64.img" \
-F "label=debian-bookworm-arm64-espressobin-rc1" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
**Parameters:**
- `image` (file, required): Boot image (FAT32/ext4)
- `label` (string, optional): Human-readable label
**Processing:**
1. Stream to temp file with `.tmp` suffix
2. Calculate SHA256 during streaming
3. Validate filesystem magic & size (16 MiB4 GiB)
4. Extract boot files to `tftp/` (if extractable: Image, dtb, initrd)
5. Atomic rename to `images/<sha256>.img`
6. Update shadow symlink
**Response (201 Created):**
```json
{
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z",
"label": "debian-bookworm-arm64-espressobin-rc1",
"tftp_ready": true
}
```
**Response (400 Bad Request) — Invalid image:**
```json
{
"error": "Invalid filesystem",
"detail": "Image size must be 16 MiB4 GiB"
}
```
#### POST `/api/v1/eye-remote/boot-media/swap`
**Request:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
```
**Optional parameters:**
- `verify=true` (default): Verify LUN re-attached successfully
**Processing:**
1. Check shadow exists and is valid
2. Eject LUN from gadget
3. Swap symlinks: `active``shadow`, `r1` ← old `active`
4. Shift rollback chain: `r2``r1`, `r3``r2`, `r4``r3`
5. Clear shadow slot
6. Re-attach LUN
7. Update state.json
**Response (200 OK):**
```json
{
"success": true,
"message": "Boot slot swapped successfully",
"active": {
"path": "images/f0e1d2c3b4a5.img",
"sha256": "f0e1d2c3b4a5...",
"size_bytes": 268435456,
"created_at": "2026-04-23T11:45:00Z"
},
"rollback_available": ["r1", "r2", "r3", "r4"]
}
```
**Response (409 Conflict) — Shadow not ready:**
```json
{
"error": "No shadow to swap",
"detail": "Upload an image to shadow before promoting"
}
```
#### POST `/api/v1/eye-remote/boot-media/rollback`
**Request:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
```
**Parameters:**
- `target` (string): Rollback slot to restore (`r1`, `r2`, `r3`, or `r4`)
**Processing:**
1. Check target exists
2. Eject LUN
3. Promote target to active, rotate chain
4. Re-attach LUN
**Response (200 OK):**
```json
{
"success": true,
"message": "Restored from r1",
"active": {
"path": "images/a1b2c3d4e5f6.img",
"sha256": "a1b2c3d4e5f6...",
"size_bytes": 268435456,
"created_at": "2026-04-23T10:30:00Z"
}
}
```
#### GET `/api/v1/eye-remote/boot-media/tftp/status`
**Request:**
```bash
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status
```
**Response (200 OK):**
```json
{
"enabled": true,
"dnsmasq_running": true,
"port": 69,
"root": "/var/lib/secubox/eye-remote/boot-media/tftp",
"shadow": {
"path": "images/f0e1d2c3b4a5.img",
"label": "debian-bookworm-arm64-espressobin-rc1"
},
"files": [
{
"name": "Image",
"size": 12582912,
"type": "kernel"
},
{
"name": "device-tree.dtb",
"size": 65536,
"type": "devicetree"
},
{
"name": "initrd.img",
"size": 8388608,
"type": "initramfs"
}
]
}
```
---
## Workflow Examples
### Workflow 1: Upload New Image
```bash
#!/bin/bash
# 1. Generate JWT token (login as boot:write user)
JWT=$(curl -s -X POST http://10.55.0.1:8000/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"boot-admin","password":"secubox-bootstrap"}' | jq -r .access_token)
# 2. Upload new image to shadow
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm-arm64-espressobin-rc1.img" \
-F "label=RC1 Build $(date +%Y%m%d)" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
# 3. Check current state
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | jq .
# Output:
# {
# "active": { ... old image ... },
# "shadow": { ... new image just uploaded ... },
# "tftp_armed": true,
# ...
# }
```
### Workflow 2: Test via TFTP (Optional)
No API call needed! The shadow is immediately available via TFTP.
```bash
# On ESPRESSObin U-Boot console:
=> setenv serverip 10.55.0.2
=> setenv ipaddr 10.55.0.1
=> tftpboot $kernel_addr_r Image
=> booti $kernel_addr_r - $fdt_addr_r
# Boot logs appear on serial console via Eye Remote
```
If the test kernel panics or fails, just reboot: U-Boot will load the **active** slot from the USB LUN (unchanged).
### Workflow 3: Promote Shadow to Active
Once shadow is tested and stable:
```bash
# 1. Get JWT (already have from upload)
JWT=$(...)
# 2. Promote shadow to active
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/swap
# Response shows active now contains the RC1 image,
# old active is saved in r1, and shadow is cleared.
# 3. Reboot ESPRESSObin (or power cycle)
# U-Boot will now load the new kernel from LUN
```
### Workflow 4: Boot from LUN
On ESPRESSObin U-Boot console:
```bash
=> usb start
=> usb tree
# Output:
# USB device tree:
# 1 Hub (480 Mb/s, 0mA)
# | ├─ 1.1 Mass Storage (active boot media)
# └─ ...
=> fatload usb 0 $kernel_addr_r Image
=> fatload usb 0 $fdt_addr_r device-tree.dtb
=> fatload usb 0 $initrd_addr_r initrd.img
=> booti $kernel_addr_r $initrd_addr_r:$initrd_size $fdt_addr_r
```
### Workflow 5: Rollback to Previous
If the active image becomes corrupted or unstable:
```bash
# 1. Check available rollback points
curl -H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/state | \
jq .rollback_available
# Output: ["r1", "r2", "r3", "r4"]
# 2. Rollback to r1 (most recent previous)
curl -X POST \
-H "Authorization: Bearer $JWT" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/rollback?target=r1
# Response confirms active is now restored from r1
# r1 contents moved to r2, r2→r3, r3→r4, r4 cleared
# 3. Reboot ESPRESSObin — boots old kernel again
```
---
## Image Requirements
### Format
- **Supported:** FAT16, FAT32, ext2, ext3, ext4
- **Recommended:** FAT32 (maximum U-Boot compatibility)
### Size
- **Minimum:** 16 MiB (allows room for kernel + DTB + initrd)
- **Maximum:** 4 GiB (USB mass storage practical limit)
- **Typical:** 256 MiB1 GiB
### Contents
**Required (for USB LUN boot):**
- Kernel image (`Image` for arm64, `zImage` for arm32)
- Device tree binary (`device-tree.dtb` or `<board>.dtb`)
**Optional:**
- Initial ramdisk (`initrd.img`)
- U-Boot environment variables
- Boot script
**Example FAT32 structure:**
```
/Image ← Kernel (required)
/device-tree.dtb ← Device tree (required)
/initrd.img ← Initramfs (optional)
/uEnv.txt ← U-Boot environment (optional)
/boot.scr ← Boot script (optional)
```
### Validation
The Eye Remote validates images on upload:
1. **Filesystem magic:** Check magic bytes for FAT or ext
2. **Size check:** Enforce 16 MiB4 GiB bounds
3. **Extractability:** For TFTP, attempt to extract Image, dtb, initrd
4. **SHA256 digest:** Compute and store for integrity tracking
If validation fails, upload rejects with 400 Bad Request.
---
## Configuration
### secubox.conf
The Eye Remote bootstrap respects the following settings in `/etc/secubox/secubox.conf`:
```toml
[eye_remote]
enabled = true
bootstrap_enabled = true
bootstrap_root = "/var/lib/secubox/eye-remote/boot-media"
max_image_size_gb = 4
min_image_size_mb = 16
[eye_remote.tftp]
enabled = true
dnsmasq_config = "/etc/dnsmasq.d/secubox-eye-remote-tftp.conf"
port = 69
[eye_remote.gadget]
ecm_enabled = true
acm_enabled = true
mass_storage_enabled = true
```
### TFTP DHCP Configuration (dnsmasq)
**File:** `/etc/dnsmasq.d/secubox-eye-remote-tftp.conf`
```ini
# TFTP service for Eye Remote bootstrap
enable-tftp
tftp-root=/var/lib/secubox/eye-remote/boot-media/tftp
tftp-port=69
listen-address=10.55.0.2
# Allow read from tftp root only (security)
tftp-secure
# Increase timeout for large initrd
tftp-max-block-size=1024
```
### Power Ordering
**Note:** The Eye Remote gadget attaches the LUN immediately on startup. ESPRESSObin U-Boot is responsible for detecting the LUN and initiating `usb start`.
**Recommended sequence:**
1. Power on ESPRESSObin (U-Boot starts, waits for user input)
2. Plug in USB OTG cable to Eye Remote
3. Wait 2 seconds for USB enumeration
4. Press Enter on U-Boot to interrupt autoboot
5. Issue `usb start` command
6. Issue `fatload usb 0 ...` to load kernel
---
## Troubleshooting
### Issue: "LUN not visible on ESPRESSObin"
**Symptoms:**
- `usb start` shows no Mass Storage device
- `usb tree` lists only hub, no LUN
**Diagnosis:**
```bash
# On Eye Remote (host):
ssh pi@eye-remote.local
systemctl status secubox-eye-remote-gadget
# Check if gadget tree exists:
ls -la /sys/kernel/config/usb_gadget/secubox/functions/mass_storage.usb0/
```
**Solutions:**
1. **Restart gadget:**
```bash
systemctl restart secubox-eye-remote-gadget
```
2. **Check active symlink exists:**
```bash
ls -la /var/lib/secubox/eye-remote/boot-media/active
# Should point to a real image file
```
3. **Verify file is readable:**
```bash
ls -lah /var/lib/secubox/eye-remote/boot-media/images/
# Files should have read permissions
```
4. **Check USB connection physically:**
- Use DATA port (middle), not PWR port
- Try a different USB cable or port
- Verify no USB hub between Eye Remote and ESPRESSObin
### Issue: "TFTP timeout / Image not found"
**Symptoms:**
- `tftpboot` hangs or reports "not found"
- TFTP root path incorrect
**Diagnosis:**
```bash
# Check TFTP service:
curl http://10.55.0.1:8000/api/v1/eye-remote/boot-media/tftp/status | jq .
# Check shadow symlink:
ls -la /var/lib/secubox/eye-remote/boot-media/tftp/
# Verify dnsmasq TFTP is running:
ps aux | grep dnsmasq
netstat -tlnup | grep :69
```
**Solutions:**
1. **Upload image to shadow first:**
```bash
curl -X POST \
-H "Authorization: Bearer $JWT" \
-F "image=@debian-bookworm.img" \
http://10.55.0.1:8000/api/v1/eye-remote/boot-media/upload
```
2. **Verify network connectivity:**
```bash
# On ESPRESSObin U-Boot:
=> ping 10.55.0.2
# Should respond with host IP
```
3. **Check file extraction succeeded:**
- TFTP status should show `files` array non-empty
- If image is raw (no filesystem), extract must fail gracefully
- Fall back to using LUN boot instead
### Issue: "Swap failed / LUN ejection timeout"
**Symptoms:**
- `POST /swap` returns 500 error
- LUN remains stuck in gadget
**Diagnosis:**
```bash
# Check gadget lock:
lsof | grep /var/lib/secubox/eye-remote/boot-media/
# Check gadget-setup.sh log:
journalctl -u secubox-eye-remote-gadget -n 50
# Verify file lock isn't held:
ps aux | grep eye-remote
```
**Solutions:**
1. **Force-eject via shell (careful!):**
```bash
sudo /usr/sbin/gadget-setup.sh swap-lun ""
sleep 0.5
sudo /usr/sbin/gadget-setup.sh swap-lun \
"/var/lib/secubox/eye-remote/boot-media/active"
```
2. **Restart gadget service:**
```bash
systemctl stop secubox-eye-remote-gadget
sleep 2
systemctl start secubox-eye-remote-gadget
```
3. **Check for stale processes:**
```bash
systemctl status secubox-eye-remote-api
# If API process holds lock, restart it
systemctl restart secubox-eye-remote-api
```
### Issue: "Invalid filesystem on upload"
**Symptoms:**
- `POST /upload` returns 400 Bad Request
- Error: "Invalid filesystem" or "Size out of range"
**Solutions:**
1. **Verify image format:**
```bash
file debian-bookworm.img
# Should output: FAT boot sector, x86 or x64 boot loader binary
# or: Linux rev 1.0 ext4 filesystem
```
2. **Check image size:**
```bash
ls -lh debian-bookworm.img
# Should be between 16 MiB and 4 GiB
```
3. **Create valid FAT32 image if needed:**
```bash
# Create 256 MiB FAT32 image
fallocate -l 256M debian-bookworm.img
mkfs.vfat -F32 debian-bookworm.img
# Mount and copy kernel files
sudo mount debian-bookworm.img /mnt/boot
sudo cp Image /mnt/boot/
sudo cp device-tree.dtb /mnt/boot/
sudo umount /mnt/boot
```
---
## See Also
- **[Eye Remote Hardware](Eye-Remote-Hardware.md)** — Physical connections, pin assignments
- **[Eye Remote Gateway](Eye-Remote-Gateway.md)** — Network configuration, DHCP/DNS
- **[Eye Remote Implementation](Eye-Remote-Implementation.md)** — Python/Bash internals, codebase structure
- **[Architecture Boot](Architecture-Boot.md)** — Overall boot architecture for SecuBox-Deb
- **[U-Boot Documentation](../eye-remote/uboot-bootcmd.md)** — ESPRESSObin U-Boot commands
---
**CyberMind · SecuBox-Deb · Eye Remote Bootstrap v2.1.0**
*Last reviewed: 2026-04-23 · Maintainer: Gerald Kerma <gandalf@cybermind.fr>*

@ -10,8 +10,9 @@
6. [Display Configuration](#display-configuration)
7. [API Reference](#api-reference)
8. [Development Tools](#development-tools)
9. [Deployment](#deployment)
10. [Lessons Learned](#lessons-learned)
9. [Bootstrap Role](#bootstrap-role)
10. [Deployment](#deployment)
11. [Lessons Learned](#lessons-learned)
---
@ -417,6 +418,80 @@ secubox-eye-gateway --profile stressed --port 8765
---
## Bootstrap Role (v2.1.0)
The Eye Remote can serve as a boot device for ESPRESSObin and MOCHAbin appliances, providing critical functionality during system initialization and recovery:
### Capabilities
- **Mass Storage LUN** — U-Boot loads kernel/DTB/initrd from active slot via USB Mass Storage
- **TFTP Shadow** — Test new images before promoting to active slot
- **Atomic Swap** — Safe active/shadow slot exchange with rollback protection
- **Boot Menu** — Interactive selection of kernel versions and boot parameters
### Use Cases
| Use Case | Benefit |
|----------|---------|
| **Factory Reset** | Boot fresh image without physical SD cards |
| **Recovery Boot** | Fallback when internal storage is corrupted |
| **Image Testing** | Try new Debian images before committing |
| **Firmware Updates** | Safe A/B slot switching with 4R rollback |
### Architecture
The Eye Remote exposes two USB LUNs:
1. **LUN 0** — Mass Storage (active boot image)
- Kernel + DTB + initrd partition
- Auto-synced from active slot
2. **LUN 1** — Shadow Test Storage
- Staging area for new images
- Isolated from live system
### Configuration
Bootstrap is configured in `/etc/secubox/eye-remote.toml`:
```toml
[bootstrap]
enabled = true
mass_storage_lun = 0
shadow_lun = 1
auto_sync_interval = 300 # 5 minutes
max_rollback_slots = 4
```
### Workflow
```
1. User initiates image test via dashboard
2. Eye Remote downloads image to shadow LUN
3. User selects "Boot from Shadow" in U-Boot menu
4. System tests image on next reboot
5. User confirms success → Image promoted to active
6. Or rejects → Automatic rollback to previous active
```
### Security Considerations
- Bootstrap operations are **JWT-authenticated** only
- All slot operations are **logged** to audit trail
- Image integrity verified via **SHA256 checksums**
- Rollback protected against **malicious substitution** via timestamp validation
---
**Full documentation:** See [Eye-Remote-Bootstrap](Eye-Remote-Bootstrap.md) for detailed implementation, testing procedures, and troubleshooting.
---
## Deployment
### SD Card Flashing

@ -1,253 +1,115 @@
# SecuBox Eye Remote
# 👁️ Eye Remote — Addon
The **SecuBox Eye Remote** is a multi-functional remote control device built on the RPi Zero W with HyperPixel 2.1 Round display (480x480px). It transforms a simple status dashboard into a powerful debugging and security tool.
**SecuBox Eye Remote** — Addon de monitoring USB gadget pour SecuBox OS.
## Overview
> **Note:** Eye Remote est un **addon optionnel** pour SecuBox OS.
> Il n'est pas nécessaire pour utiliser SecuBox OS, mais offre un affichage
> déporté pratique pour le monitoring et le débogage.
```
┌─────────────────────────────────────┐
│ ● SECUBOX EYE │
│ NORMAL MODE │
│ │
│ ╔═══════════╗ │
│ ║ 14:32:07 ║ │
│ ║ NOMINAL ║ │
│ ╚═══════════╝ │
│ │
│ [AUTH] [WALL] [BOOT] │
│ [MIND] [ROOT] [MESH] │
│ │
│ ════════════════════ │
│ TEMP [████████░░] 44°C │
└─────────────────────────────────────┘
HyperPixel 2.1 Round
```
## USB Gadget Modes
The Eye Remote supports **5 operational modes** via USB OTG composite gadget:
| Command | Mode | Functions |
|---------|------|-----------|
| `start` | Normal | Network (ECM) + Serial |
| `flash` | Recovery | Bootable USB + Serial (U-Boot access) |
| `debug` | Debug | Network + Storage + Serial |
| `tty` | Keyboard | Virtual keyboard + Serial (automation) |
| `auth` | Eye Remote | FIDO/U2F HID + QR display (security key) |
### Smart Auto-Mode
The gadget service uses **auto-detection** by default:
```bash
# Auto-detect optimal mode at boot
secubox-otg-gadget.sh auto
# Set persistent mode (survives reboot)
secubox-otg-gadget.sh set-mode tty
# Clear persistent mode
secubox-otg-gadget.sh clear-mode
```
Detection priority:
1. Persistent mode from `/etc/secubox/gadget-mode`
2. Flash mode trigger file
3. TTY mode from command queue presence
4. Auth mode from state file
5. Default: Normal mode
## Hardware Requirements
| Component | Reference | Notes |
|-----------|-----------|-------|
| RPi Zero W | v1.1 or Zero 2 W | WiFi integrated |
| HyperPixel 2.1 Round | Pimoroni PIM578 | 480x480 capacitive touch |
| microSD | 8GB+ Class 10 | Endurance recommended |
| USB cable | Data-capable | **Must be DATA, not power-only** |
## Quick Start
### 1. Flash SD Card
```bash
cd secubox-deb/remote-ui/round
# Download RPi OS Lite (32-bit armhf required)
wget https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-11-19/2024-11-19-raspios-bookworm-armhf-lite.img.xz
# Flash with USB OTG enabled
sudo ./install_zerow.sh \
-d /dev/sdX \
-i 2024-11-19-raspios-bookworm-armhf-lite.img.xz \
-s "YourWiFi" \
-p "YourPassword" \
-k ~/.ssh/id_rsa.pub \
-r # Enable USB OTG
```
### 2. Connect Hardware
```
┌──────────────────────────┐
│ HyperPixel Round │
│ [GPIO Header] │
└──────────┬───────────────┘
┌──────────┴───────────────┐
│ Raspberry Pi Zero W │
│ [PWR] [DATA] [HDMI] │
│ ○ ● ○ │
│ ↑ │
│ Connect USB here │
└──────────────────────────┘
```
**Important:** Connect USB to DATA port (middle), not PWR!
### 3. Deploy Dashboard
```bash
./deploy.sh -h 10.55.0.2 --api-url http://10.55.0.1:8000
```
## Mode Details
### Normal Mode
Standard monitoring mode with network and serial access.
- **ECM Network**: `10.55.0.2/30` (gadget) ↔ `10.55.0.1/30` (host)
- **Serial Console**: `/dev/ttyGS0` @ 115200 baud
### Flash Mode
Bootable USB recovery for eMMC flashing.
```bash
secubox-otg-gadget.sh flash /path/to/secubox-image.img
```
The target SecuBox boots from USB and can flash its eMMC.
### Debug Mode
Full debugging with network + mass storage for log export.
```bash
secubox-otg-gadget.sh debug
```
Exported to USB storage:
- `/var/log/secubox/`
- `/etc/secubox/`
- Runtime state
### TTY Mode
Virtual HID keyboard for U-Boot automation.
```bash
# Enter TTY mode
secubox-otg-gadget.sh tty
# Send commands
secubox-hid-keyboard.sh cmd 'printenv'
secubox-hid-keyboard.sh cmd 'setenv bootcmd run bootusb'
secubox-hid-keyboard.sh cmd 'saveenv'
secubox-hid-keyboard.sh cmd 'boot'
# Process command queue
secubox-hid-keyboard.sh queue /run/secubox-cmd-queue
```
### Auth Mode (Eye Remote)
FIDO2/U2F security key with QR display.
```bash
secubox-otg-gadget.sh auth
```
- Hardware security key for SSH/WebAuthn
- QR code display for backup codes
- Touch-to-approve authentication
## Network Configuration
| Interface | IP Address | Device |
|-----------|------------|--------|
| SecuBox Host | 10.55.0.1/30 | `secubox-round` |
| Eye Remote | 10.55.0.2/30 | `usb0` |
## Status Files
| File | Purpose |
|------|---------|
| `/run/secubox-gadget-status.json` | Current mode and state |
| `/run/secubox-cmd-queue` | TTY mode command queue |
| `/run/secubox-auth-state.json` | Auth mode challenge state |
| `/etc/secubox/gadget-mode` | Persistent mode setting |
## Round UI Mode Selector
The dashboard includes a touch-friendly mode selector at the top center:
1. Tap the mode badge to open selector
2. Choose new mode
3. Mode switches via API or local script
4. Badge updates with mode color
## x64 Live Boot Support
The Eye Remote dashboard also runs on x64 systems:
```bash
# Build live USB with Eye Remote
./image/build-live-usb.sh --profile x64-live --eye-remote
# Test in VM
qemu-system-x86_64 -m 2G -cdrom secubox-eye-live.iso
```
## Troubleshooting
### USB Not Detected
1. Verify using DATA port, not PWR
2. Check USB cable supports data
3. Run `dmesg | grep -i cdc` on host
### Mode Switch Fails
```bash
# Check status
secubox-otg-gadget.sh status
# Force restart
sudo secubox-otg-gadget.sh restart
# View logs
journalctl -u secubox-otg-gadget -f
```
### Display Black
```bash
# Check HyperPixel overlay
cat /boot/firmware/config.txt | grep hyperpixel
# Check DRM
ls -la /dev/dri/
```
## Related Documentation
- [README](https://github.com/CyberMind-FR/secubox-deb/blob/master/remote-ui/round/README.md)
- [Technical Wiki](https://github.com/CyberMind-FR/secubox-deb/blob/master/remote-ui/round/WIKI.md)
- [Roadmap](https://github.com/CyberMind-FR/secubox-deb/blob/master/remote-ui/round/ROADMAP.md)
- [Issue #30](https://github.com/CyberMind-FR/secubox-deb/issues/30)
**Hardware:** Raspberry Pi Zero W + HyperPixel 2.1 Round (480×480)
---
*SecuBox Eye Remote v1.8.0 — CyberMind*
## Pour qui ?
| Cas d'usage | Description |
|-------------|-------------|
| **Datacenter** | Monitoring visuel sans écran sur appliance |
| **Debug terrain** | Console série + affichage status |
| **Démonstration** | Dashboard compact pour salons/présentations |
| **Récupération** | Boot USB de secours via mass storage |
---
## Documentation
| Page | Description |
|------|-------------|
| [[Eye-Remote-Hardware]] | Configuration matérielle, GPIO, display |
| [[Eye-Remote-Implementation]] | Architecture logicielle, agent, renderer |
| [[Eye-Remote-Bootstrap]] | Boot device, slots A/B, mass storage |
| [[Eye-Remote-Gateway]] | Émulateur gateway pour tests |
---
## Features
### Dashboard circulaire
- Affichage framebuffer 480×480 rond
- 6 anneaux de status (AUTH, WALL, BOOT, MIND, ROOT, MESH)
- Métriques temps réel SecuBox
- Navigation tactile
### Connexion USB OTG
- **CDC-ECM** : réseau 10.55.0.2 ↔ 10.55.0.1
- **CDC-ACM** : console série
- **Mass Storage** : images de boot
### Boot Device (optionnel)
- Slots A/B pour boot media
- Swap atomique pour mises à jour sécurisées
- Rollback 4 niveaux (R1-R4)
- Serveur TFTP netboot
---
## Schéma de connexion
```
┌─────────────────┐ USB OTG ┌─────────────────┐
│ Eye Remote │◄────────────────►│ SecuBox OS │
│ Pi Zero W │ 10.55.0.0/30 │ Appliance │
│ HyperPixel 2.1 │ │ │
└─────────────────┘ └─────────────────┘
│ │
│ Display │ LAN/WAN
▼ ▼
┌─────────┐ ┌─────────┐
│ 480×480 │ │ Network │
│ Round │ │ Clients │
└─────────┘ └─────────┘
```
---
## Build & Deploy
```bash
# Prérequis: SecuBox OS déjà déployé sur l'appliance cible
# Build image Eye Remote
cd remote-ui/round
sudo ./build-eye-remote-image.sh -i raspios-lite.img.xz
# Flasher sur carte SD
sudo dd if=eye-remote.img of=/dev/sdX bs=4M status=progress
# Brancher le Pi Zero W sur le port USB de l'appliance SecuBox
# (port DATA, pas PWR)
```
---
## Palette de couleurs
| Module | Couleur | Hex |
|--------|---------|-----|
| AUTH | Orange | #C04E24 |
| WALL | Jaune-brun | #9A6010 |
| BOOT | Rouge-brun | #803018 |
| MIND | Violet | #3D35A0 |
| ROOT | Vert | #0A5840 |
| MESH | Bleu | #104A88 |
Voir [[eye-remote-icons]] pour la référence des icônes.
---
## Traductions
- [[Eye-Remote-Bootstrap-FR|Français]]
- [[Eye-Remote-Bootstrap-ZH|中文]]
---
*← Retour à [[Home|SecuBox OS]]*

187
Home.md

@ -1,54 +1,177 @@
# SecuBox-DEB Wiki
# SecuBox OS
Welcome to the SecuBox-DEB documentation wiki.
**CyberMind · Gondwana · Notre-Dame-du-Cruet · Savoie** | [FR](Home-FR) | [中文](Home-ZH)
## Eye Remote
**SecuBox OS** — Appliance de cybersécurité complète portée depuis OpenWrt vers Debian bookworm.
Conçue pour boards ARM64 GlobalScale (MOCHAbin, ESPRESSObin) et systèmes x86_64.
The Eye Remote is a compact USB gadget display for monitoring SecuBox metrics.
**125 modules · 2000+ endpoints API · Candidat ANSSI CSPN**
| Page | Description |
|------|-------------|
| [Eye Remote Implementation](Eye-Remote-Implementation.md) | Architecture, API, and implementation guide |
| [Eye Remote Hardware](Eye-Remote-Hardware.md) | Hardware setup, GPIO pinout, display configuration |
| [Eye Remote Gateway](Eye-Remote-Gateway.md) | Gateway emulator for development and testing |
---
### Quick Start
## Qu'est-ce que SecuBox OS ?
1. **Hardware**: Raspberry Pi Zero W + HyperPixel 2.1 Round (480×480)
2. **Connection**: USB OTG (10.55.0.0/30) or WiFi
3. **Dashboard**: Python framebuffer rendering (no browser needed)
SecuBox OS est un système d'exploitation durci orienté sécurité réseau :
### Build Image
| Fonction | Description |
|----------|-------------|
| **Firewall** | nftables DEFAULT DROP, règles automatiques |
| **IDS/IPS** | CrowdSec + Suricata, threat intelligence temps réel |
| **WAF** | HAProxy + mitmproxy, 300+ règles ModSecurity |
| **VPN** | WireGuard natif, mesh P2P |
| **DPI** | nDPId + netifyd, analyse trafic L7 |
| **DNS** | Unbound Vortex, blocklists automatiques |
---
## 🔴 BOOT — Démarrage rapide
### VirtualBox (Recommandé)
```bash
# Lightweight framebuffer mode (recommended)
cd remote-ui/round
sudo ./build-eye-remote-image.sh -i raspios-lite.img.xz --framebuffer
# With WiFi pre-configured
sudo ./build-eye-remote-image.sh -i raspios-lite.img.xz -s "SSID" -p "password"
# One-liner avec téléchargement auto
curl -sL https://raw.githubusercontent.com/CyberMind-FR/secubox-deb/master/image/create-vbox-vm.sh | bash -s -- --download
```
### Test with Emulator
Voir [[Live-USB-VirtualBox]] pour les détails.
### Live USB
```bash
# Start gateway emulator
cd tools/secubox-eye-gateway
pip install -e .
secubox-eye-gateway --profile stressed --port 8765
wget https://github.com/CyberMind-FR/secubox-deb/releases/latest/download/secubox-live-amd64-bookworm.img.gz
zcat secubox-live-amd64-bookworm.img.gz | sudo dd of=/dev/sdX bs=4M status=progress
```
# Test on desktop (requires pygame)
cd remote-ui/round
python3 test-dashboard-amd64.py --api http://localhost:8765
Voir [[Live-USB]] pour le guide complet.
### Installation APT
```bash
curl -fsSL https://apt.secubox.in/install.sh | sudo bash
sudo apt install secubox-full
```
---
## Other Documentation
## 🟠 AUTH — Accès
- [CLAUDE.md](../../CLAUDE.md) — Project conventions and migration guide
- [Porting Guide](../PORTING-GUIDE.md) — OpenWrt to Debian migration
| Service | Utilisateur | Mot de passe | Port |
|---------|-------------|--------------|------|
| Web UI | admin | secubox | 9443 |
| SSH | root | secubox | 2222 |
---
*CyberMind · SecuBox-DEB · April 2026*
## 🟢 ROOT — Matériel supporté
### ARM64 (Production)
| Board | SoC | Profil | Usage |
|-------|-----|--------|-------|
| MOCHAbin | Armada 7040 | Full | Entreprise, datacenter |
| ESPRESSObin v7 | Armada 3720 | Lite | PME, agences |
| ESPRESSObin Ultra | Armada 3720 | Lite+ | PME étendu |
### x86_64 (Dev/Test)
| Plateforme | Profil | Usage |
|------------|--------|-------|
| VirtualBox | Full | Développement |
| QEMU/KVM | Full | Test/CI |
| Bare metal | Full | Production x86 |
---
## 🟣 MIND — Stack modulaire
SecuBox OS est organisé en 6 stacks fonctionnelles :
| Stack | Code couleur | Modules clés |
|-------|--------------|--------------|
| 🟠 **AUTH** | Orange | auth, portal, nac, users |
| 🟡 **WALL** | Jaune | crowdsec, waf, ipblock, threats |
| 🔴 **BOOT** | Rouge | cloner, vault, vm, backup |
| 🟣 **MIND** | Violet | dpi, ai-insights, netdata |
| 🟢 **ROOT** | Vert | core, hub, system, admin |
| 🔵 **MESH** | Bleu | wireguard, haproxy, qos, mesh |
Voir [[Modules]] pour les 125 modules.
---
## 🔵 MESH — Documentation
### Démarrage
- [[Live-USB-VirtualBox|VirtualBox]]
- [[Live-USB|USB Boot]]
- [[ARM-Installation|Boards ARM]]
- [[QEMU-ARM64|Émulation QEMU]]
### Configuration
- [[Configuration]]
- [[Configuration-Advanced]]
- [[Troubleshooting]]
### Architecture
- [[Architecture-Boot|Couches de boot]]
- [[Architecture-Modules|Design modulaire]]
- [[Architecture-Security|Modèle de sécurité]]
### Développement
- [[Developer-Guide]]
- [[Design-System|UI/UX]]
- [[API-Reference]]
---
## 🟡 WALL — Sécurité
### Firewall & IDS
- **nftables** — DEFAULT DROP, règles dynamiques
- **CrowdSec** — IDS communautaire, bouncer automatique
- **Suricata** — Signatures ET Open
### WAF & Inspection
- **HAProxy** — TLS 1.3, load balancing
- **mitmproxy** — Inspection HTTPS transparente
- **300+ règles** — OWASP ModSecurity CRS
### AI & Threat Intel
- **AI-Insights** — Détection ML anomalies
- **Threat feeds** — AbuseIPDB, Emerging Threats
- **Geo-blocking** — Blocage par pays
---
## Addons
### 👁️ Eye Remote (Addon)
Dashboard USB gadget compact pour monitoring SecuBox.
| Composant | Description |
|-----------|-------------|
| Hardware | Pi Zero W + HyperPixel 2.1 Round (480×480) |
| Connexion | USB OTG (10.55.0.0/30) ou WiFi |
| Modes | Normal, Flash, Debug, TTY, Auth |
**Documentation :** [[Eye-Remote|Eye Remote Addon]]
```bash
# Build image Pi Zero W
cd remote-ui/round
sudo ./build-eye-remote-image.sh -i raspios-lite.img.xz
```
---
## Liens
- [GitHub](https://github.com/CyberMind-FR/secubox-deb)
- [Releases](https://github.com/CyberMind-FR/secubox-deb/releases)
- [APT Repository](https://apt.secubox.in)
- [CyberMind](https://cybermind.fr)
---
*© 2026 CyberMind · Notre-Dame-du-Cruet, Savoie*

1889
Modules.md

File diff suppressed because it is too large Load Diff

@ -1,12 +1,49 @@
## Navigation
**[SecuBox OS](Home)** · [FR](Home-FR) · [中文](Home-ZH)
**[Home](Home)**
---
### Eye Remote
- [Implementation](Eye-Remote-Implementation)
- [Hardware](Eye-Remote-Hardware)
- [Gateway & Emulator](Eye-Remote-Gateway)
## SecuBox OS
### Project
- [Migration Guide](../PORTING-GUIDE)
- [CLAUDE.md](../../CLAUDE)
### 🔴 BOOT — Démarrage
* [[Home|Overview]]
* [[Live-USB-VirtualBox|VirtualBox]]
* [[Live-USB|USB Boot]]
* [[Installation|APT Install]]
* [[ARM-Installation|Boards ARM]]
### 🟢 ROOT — Configuration
* [[Configuration]]
* [[Configuration-Advanced]]
* [[Troubleshooting]]
### 🟣 MIND — Architecture
* [[Architecture-Boot|Boot Layers]]
* [[Architecture-Modules|Modules]]
* [[Architecture-Security|Security]]
### 🟡 WALL — Modules
* [[Modules|All Modules (125)]]
* [[Modules-Security]]
* [[Modules-Networking]]
### 🔵 MESH — Dev
* [[Developer-Guide]]
* [[Design-System]]
* [[API-Reference]]
---
## Addons
### 👁️ Eye Remote
* [[Eye-Remote|Overview]]
* [[Eye-Remote-Hardware|Hardware]]
* [[Eye-Remote-Implementation|Implementation]]
* [[Eye-Remote-Bootstrap|Boot Media]]
---
### Links
* [GitHub](https://github.com/CyberMind-FR/secubox-deb)
* [Releases](https://github.com/CyberMind-FR/secubox-deb/releases)
* [CyberMind](https://cybermind.fr)

267
eye-remote-icons.md Normal file

@ -0,0 +1,267 @@
# SecuBox Eye Remote - Icons Reference
> **CyberMind** - SecuBox Eye Remote Touchscreen Controller
> Hardware: RPi Zero W + HyperPixel 2.1 Round (480x480)
---
## Overview
The Eye Remote uses a radial menu system with 6 slices, each displaying an icon and label. Icons are rendered at 40x40 pixels from source files stored at `/usr/lib/secubox-eye/assets/icons/`.
---
## Icon Locations
| Path | Description |
|------|-------------|
| `/usr/lib/secubox-eye/assets/icons/` | Primary system install |
| `remote-ui/round/assets/icons/` | Source repository |
---
## Icon Sizes
Each icon is provided in multiple sizes for different use cases:
| Size | Usage |
|------|-------|
| 22px | Small UI elements |
| 48px | **Primary** - Radial menu (resized to 40px) |
| 96px | Large displays, exports |
| 128px | High-DPI displays |
---
## ROOT Menu Icons (Main Menu)
| Icon | Name | Label | Description |
|------|------|-------|-------------|
| ![devices](../../remote-ui/round/assets/icons/devices-48.png) | `devices` | DEVICES | Connected SecuBox devices |
| ![secubox](../../remote-ui/round/assets/icons/secubox-48.png) | `secubox` | SECUBOX | Active SecuBox status |
| ![local](../../remote-ui/round/assets/icons/local-48.png) | `local` | LOCAL | Pi Zero W local settings |
| ![network](../../remote-ui/round/assets/icons/network-48.png) | `network` | NETWORK | Network configuration |
| ![security](../../remote-ui/round/assets/icons/security-48.png) | `security` | SECURITY | Security & alerts |
| ![exit](../../remote-ui/round/assets/icons/exit-48.png) | `exit` | EXIT | Exit menu / system actions |
---
## Navigation Icons
| Icon | Name | Usage |
|------|------|-------|
| ![back](../../remote-ui/round/assets/icons/back-48.png) | `back` | Return to previous menu |
| ![dashboard](../../remote-ui/round/assets/icons/dashboard-48.png) | `dashboard` | Return to dashboard |
---
## Action Icons
| Icon | Name | Action |
|------|------|--------|
| ![scan](../../remote-ui/round/assets/icons/scan-48.png) | `scan` | Scan for devices |
| ![plus](../../remote-ui/round/assets/icons/plus-48.png) | `plus` | Add / Pair new |
| ![refresh](../../remote-ui/round/assets/icons/refresh-48.png) | `refresh` | Refresh data |
| ![restart](../../remote-ui/round/assets/icons/restart-48.png) | `restart` | Restart service |
| ![update](../../remote-ui/round/assets/icons/update-48.png) | `update` | Check updates |
| ![trash](../../remote-ui/round/assets/icons/trash-48.png) | `trash` | Delete / Forget |
---
## System Icons
| Icon | Name | Category |
|------|------|----------|
| ![cpu](../../remote-ui/round/assets/icons/cpu-48.png) | `cpu` | CPU status |
| ![memory](../../remote-ui/round/assets/icons/memory-48.png) | `memory` | RAM usage |
| ![disk](../../remote-ui/round/assets/icons/disk-48.png) | `disk` | Storage |
| ![temp](../../remote-ui/round/assets/icons/temp-48.png) | `temp` | Temperature |
| ![clock](../../remote-ui/round/assets/icons/clock-48.png) | `clock` | Uptime / Time |
---
## Display Icons
| Icon | Name | Function |
|------|------|----------|
| ![display](../../remote-ui/round/assets/icons/display-48.png) | `display` | Display settings |
| ![brightness](../../remote-ui/round/assets/icons/brightness-48.png) | `brightness` | Brightness control |
| ![theme](../../remote-ui/round/assets/icons/theme-48.png) | `theme` | Theme selection |
| ![rotate](../../remote-ui/round/assets/icons/rotate-48.png) | `rotate` | Screen rotation |
| ![timeout](../../remote-ui/round/assets/icons/timeout-48.png) | `timeout` | Screen timeout |
| ![test](../../remote-ui/round/assets/icons/test-48.png) | `test` | Display test |
---
## Network Icons
| Icon | Name | Function |
|------|------|----------|
| ![interfaces](../../remote-ui/round/assets/icons/interfaces-48.png) | `interfaces` | Network interfaces |
| ![routes](../../remote-ui/round/assets/icons/routes-48.png) | `routes` | Routing table |
| ![dns](../../remote-ui/round/assets/icons/dns-48.png) | `dns` | DNS settings |
| ![wifi](../../remote-ui/round/assets/icons/wifi-48.png) | `wifi` | WiFi config |
| ![usb](../../remote-ui/round/assets/icons/usb-48.png) | `usb` | USB network |
| ![hostname](../../remote-ui/round/assets/icons/hostname-48.png) | `hostname` | Hostname |
| ![traffic](../../remote-ui/round/assets/icons/traffic-48.png) | `traffic` | Traffic monitor |
---
## Security Icons
| Icon | Name | Function |
|------|------|----------|
| ![alert](../../remote-ui/round/assets/icons/alert-48.png) | `alert` | Alerts |
| ![ban](../../remote-ui/round/assets/icons/ban-48.png) | `ban` | Banned IPs |
| ![rules](../../remote-ui/round/assets/icons/rules-48.png) | `rules` | Firewall rules |
| ![audit](../../remote-ui/round/assets/icons/audit-48.png) | `audit` | Audit log |
| ![lock](../../remote-ui/round/assets/icons/lock-48.png) | `lock` | Lockdown mode |
---
## System Control Icons
| Icon | Name | Action |
|------|------|--------|
| ![sleep](../../remote-ui/round/assets/icons/sleep-48.png) | `sleep` | Sleep mode |
| ![reboot](../../remote-ui/round/assets/icons/reboot-48.png) | `reboot` | Reboot Pi |
| ![shutdown](../../remote-ui/round/assets/icons/shutdown-48.png) | `shutdown` | Shutdown |
---
## SecuBox Module Icons
These icons represent SecuBox security modules:
| Icon | Name | Module |
|------|------|--------|
| ![auth](../../remote-ui/round/assets/icons/auth-48.png) | `auth` | AUTH - CrowdSec IDS |
| ![wall](../../remote-ui/round/assets/icons/wall-48.png) | `wall` | WALL - Firewall |
| ![boot](../../remote-ui/round/assets/icons/boot-48.png) | `boot` | BOOT - Boot security |
| ![mind](../../remote-ui/round/assets/icons/mind-48.png) | `mind` | MIND - DPI Analysis |
| ![root](../../remote-ui/round/assets/icons/root-48.png) | `root` | ROOT - DNS Vortex |
| ![mesh](../../remote-ui/round/assets/icons/mesh-48.png) | `mesh` | MESH - WireGuard VPN |
---
## Menu Slice Colors
| Slice | Module | Hex Color | Preview |
|-------|--------|-----------|---------|
| 0 | AUTH | `#C04E24` | ![#C04E24](https://via.placeholder.com/20/C04E24/C04E24) |
| 1 | WALL | `#9A6010` | ![#9A6010](https://via.placeholder.com/20/9A6010/9A6010) |
| 2 | BOOT | `#803018` | ![#803018](https://via.placeholder.com/20/803018/803018) |
| 3 | MIND | `#3D35A0` | ![#3D35A0](https://via.placeholder.com/20/3D35A0/3D35A0) |
| 4 | ROOT | `#0A5840` | ![#0A5840](https://via.placeholder.com/20/0A5840/0A5840) |
| 5 | MESH | `#104A88` | ![#104A88](https://via.placeholder.com/20/104A88/104A88) |
---
## Icon File Naming Convention
Icons follow this naming pattern:
```
{name}-{size}.png
```
Examples:
- `devices-48.png` - Devices icon, 48px
- `security-22.png` - Security icon, 22px
- `auth-96.png` - AUTH module icon, 96px
---
## Adding New Icons
1. Create icon in all sizes (22, 48, 96, 128px)
2. Use PNG format with RGBA (transparency support)
3. Place in `remote-ui/round/assets/icons/`
4. Reference in `menu_definitions.py` by base name (without size/extension)
Example:
```python
MenuItem("NEW ITEM", "newicon", action="module.action")
```
---
## Technical Notes
### Icon Loading Priority
The renderer searches for icons in this order:
1. `Path(__file__).parent.parent / "assets" / "icons"` (relative to module)
2. `/usr/lib/secubox-eye/assets/icons/` (system install)
3. `/usr/share/secubox-eye/icons/` (alternative)
### Size Preference
Icons are loaded in this size priority:
1. 48px (preferred for radial menu)
2. 22px (fallback)
3. 96px (fallback)
All icons are resized to 40x40px for display in the radial menu.
---
## Full Icon List
| # | Name | Sizes Available |
|---|------|-----------------|
| 1 | alert | 22, 48 |
| 2 | audit | 22, 48 |
| 3 | auth | 22, 48, 96, 128 |
| 4 | back | 22, 48 |
| 5 | ban | 22, 48 |
| 6 | boot | 22, 48, 96, 128 |
| 7 | brightness | 22, 48 |
| 8 | clock | 22, 48 |
| 9 | cpu | 22, 48 |
| 10 | dashboard | 22, 48 |
| 11 | devices | 22, 48 |
| 12 | disk | 22, 48 |
| 13 | display | 22, 48 |
| 14 | dns | 22, 48 |
| 15 | exit | 22, 48 |
| 16 | hostname | 22, 48 |
| 17 | info | 22, 48 |
| 18 | interfaces | 22, 48 |
| 19 | local | 22, 48 |
| 20 | lock | 22, 48 |
| 21 | logs | 22, 48 |
| 22 | memory | 22, 48 |
| 23 | mesh | 22, 48, 96, 128 |
| 24 | mind | 22, 48, 96, 128 |
| 25 | modules | 22, 48 |
| 26 | network | 22, 48 |
| 27 | plus | 22, 48 |
| 28 | reboot | 22, 48 |
| 29 | refresh | 22, 48 |
| 30 | restart | 22, 48 |
| 31 | root | 22, 48, 96, 128 |
| 32 | rotate | 22, 48 |
| 33 | routes | 22, 48 |
| 34 | rules | 22, 48 |
| 35 | scan | 22, 48 |
| 36 | secubox | 22, 48 |
| 37 | security | 22, 48 |
| 38 | shutdown | 22, 48 |
| 39 | sleep | 22, 48 |
| 40 | status | 22, 48 |
| 41 | system | 22, 48 |
| 42 | temp | 22, 48 |
| 43 | test | 22, 48 |
| 44 | theme | 22, 48 |
| 45 | timeout | 22, 48 |
| 46 | traffic | 22, 48 |
| 47 | trash | 22, 48 |
| 48 | update | 22, 48 |
| 49 | usb | 22, 48 |
| 50 | wall | 22, 48, 96, 128 |
| 51 | wifi | 22, 48 |
---
*CyberMind - SecuBox Eye Remote - Documentation*
*Last updated: 2026-04-25*