Applicazione di first boot per sistemi embedded/industriali con due front-end complementari:
- GUI nativa desktop realizzata in Rust + Slint;
- WebPage responsive servita direttamente dal backend Rust sulla stessa API locale.
L'obiettivo del progetto è accompagnare l'operatore nelle attività iniziali di provisioning del dispositivo: configurazione utenti, permessi, data/ora/timezone e avvio di azioni host come apply configuration, backup recovery e factory reset.
Il binario espone sempre un backend HTTP locale. A seconda di come lo lanci puoi usare:
- la GUI nativa, pensata per l'uso su dispositivo o postazione locale;
- la WebPage, utile quando vuoi operare da browser usando gli stessi endpoint.
In pratica l'architettura è questa:
- il backend Rust espone API locali su
127.0.0.1:7878di default; - la GUI Slint usa quelle API per leggere stato e inviare azioni;
- anche la WebPage usa le stesse API e viene servita dallo stesso processo Rust.
La GUI non esegue direttamente i comandi di sistema: tutte le operazioni passano dal backend HTTP locale.
cargo runQuesta è la modalità consigliata per il primo utilizzo. Il processo:
- avvia il backend locale in background;
- apre la finestra desktop Slint;
- sincronizza data, ora e timezone dalla macchina host;
- rende disponibile in parallelo anche la WebPage sulla root HTTP locale.
cargo run -- serverQuesta modalità è utile quando:
- vuoi usare solo il browser;
- stai facendo debug o test degli endpoint;
- vuoi integrare client esterni via HTTP locale.
Con il server attivo, apri nel browser:
http://127.0.0.1:7878/
Gli asset della WebPage sono serviti direttamente dal backend ai path:
GET /GET /app.cssGET /app.js
Per cambiare bind address usa la variabile d'ambiente FIRSTBOOT_API_ADDR.
Esempio backend headless:
FIRSTBOOT_API_ADDR=0.0.0.0:7878 cargo run -- serverEsempio GUI desktop:
FIRSTBOOT_API_ADDR=127.0.0.1:7879 cargo runLa GUI nativa è l'interfaccia principale per l'operatore locale. È adatta quando il dispositivo ha monitor/touch locale oppure quando vuoi un'esperienza desktop dedicata.
- barra superiore con data, ora e timezone aggiornate periodicamente;
- form guidato per i tre profili utente:
- amministratore;
- installatore;
- utente finale;
- feedback password immediato;
- selezione del livello di permesso da menu a tendina;
- popup dedicato per configurare data, ora e timezone;
- pulsanti per:
- Applica configurazione;
- Backup recovery;
- Factory reset.
Usa la GUI nativa se:
- lavori direttamente sul dispositivo;
- vuoi un'interfaccia più “appliance-like”;
- ti serve un flusso operatore lineare e focalizzato;
- vuoi ridurre al minimo il contesto tecnico visibile all'utente finale.
- Verifica data, ora e timezone nella toolbar superiore.
- Compila i tre profili utente richiesti.
- Inserisci le password e controlla il feedback di robustezza.
- Seleziona il livello di permesso per ogni profilo.
- Premi Applica configurazione.
- Se necessario usa Configura orario per correggere data/ora/timezone.
- Esegui Backup recovery o Factory reset solo quando vuoi testare o simulare quei flussi.
La WebPage è la seconda interfaccia del progetto. Non è una pagina informativa: è una vera UI operativa che usa gli stessi endpoint della GUI nativa.
- dashboard iniziale con stato host e metriche di data/ora/timezone;
- layout responsive, adatto anche a schermi più piccoli;
- sezione utenti con gli stessi tre profili della GUI;
- feedback password coerente con il client desktop;
- modal per configurare data, ora e timezone;
- area stato/output backend per leggere subito l'esito delle operazioni;
- pulsanti per apply configuration, backup recovery e factory reset.
Usa la WebPage se:
- vuoi accedere all'interfaccia da browser senza aprire la GUI desktop;
- stai facendo demo, collaudo o supporto remoto su rete locale;
- vuoi verificare rapidamente il comportamento delle API con una UI già pronta;
- preferisci un'interfaccia responsive servita direttamente dal backend.
- Apri
http://127.0.0.1:7878/. - Controlla il riquadro Stato host.
- Premi Aggiorna stato se vuoi forzare una nuova lettura.
- Compila i profili utente nella sezione centrale.
- Usa Configura orario per aprire la finestra modale e modificare data/ora/timezone.
- Premi Applica configurazione o gli altri pulsanti operativi.
- Controlla il pannello Stato operazioni per l'esito restituito dal backend.
| Aspetto | GUI nativa | WebPage |
|---|---|---|
| Tecnologia | Slint desktop | HTML/CSS/JS serviti dal backend |
| Avvio | cargo run |
cargo run -- server oppure cargo run + browser |
| Uso tipico | operatore locale sul dispositivo | accesso da browser, test, demo |
| UX | più “dedicata” e desktop | più flessibile e responsive |
| API usate | API HTTP locali | le stesse API HTTP locali |
In termini funzionali, le due interfacce sono allineate: cambia soprattutto il contesto d'uso.
Questa è la sezione più utile per capire cosa è cambiato nelle ultime revisioni del progetto.
- è stata aggiunta una WebPage responsive completa, servita direttamente dal backend Rust;
- la root
GET /ora espone la UI web invece di una semplice pagina placeholder/informativa; - GUI nativa e WebPage condividono lo stesso backend HTTP locale e gli stessi endpoint;
- la documentazione e i commenti del codice sono stati migliorati per chiarire architettura, callback e payload;
- il routing del backend è stato sistemato per servire correttamente la UI web e gli asset associati.
Oggi il progetto può essere usato in due modi reali:
- come app desktop nativa per l'operatore locale;
- come console web per browser, utile per test, demo e accesso più flessibile.
Questo rende il repository molto più vicino a una base di prodotto: non c'è più una sola GUI, ma un backend locale condiviso con due canali di accesso coerenti.
Il backend locale espone questi endpoint:
GET /GET /app.cssGET /app.jsGET /api/timePOST /api/timePOST /api/configurationPOST /api/backup-recoveryPOST /api/factory-reset
curl http://127.0.0.1:7878/api/timeRisposta tipica:
date=2026-03-22
time=10:30:15
timezone=Europe/Rome
curl -X POST http://127.0.0.1:7878/api/time \
-H 'Content-Type: text/plain' \
--data-binary $'date=2026-03-22\ntime=10:35:00\ntimezone=UTC\n'curl -X POST http://127.0.0.1:7878/api/configuration \
-H 'Content-Type: text/plain' \
--data-binary $'admin|sysadmin|System Administrator|Secret123!|0\ninstaller|fieldtech|Field Installer|Install123!|1\nviewer|operator|End User Operator|View123!|2'curl -X POST http://127.0.0.1:7878/api/backup-recoverycurl -X POST http://127.0.0.1:7878/api/factory-resetFormato testuale key=value:
date=YYYY-MM-DD
time=HH:MM:SS
timezone=Area/City
Una riga per utente, nel formato:
role|username|full_name|password|permission_idx
Dove permission_idx corrisponde alle voci del selettore permessi in UI:
0= amministratore completo;1= rete e ora di sistema;2= sola visualizzazione.
L'implementazione attuale del backend è ancora dimostrativa, ma già utile per testare il flusso end-to-end.
- Applica configurazione: serializza i tre utenti e li appende a
/tmp/firstboot-user-config.log. - Backup recovery: scrive un evento in
/tmp/firstboot-actions.loged esegueuname -a. - Factory reset: scrive un evento in
/tmp/firstboot-actions.loged eseguedate. - Salva orario: prova a invocare
timedatectl set-timezoneetimedatectl set-time.
Questo significa che il progetto è già utile come base di UX, integrazione e test, mentre il layer host può essere sostituito in seguito con logiche reali di provisioning.
src/main.rs: bootstrap dell'applicazione, avvio GUI e collegamento dei callback Slint al client API.src/api.rs: server HTTP locale minimale + client HTTP raw usato dalla GUI.src/web.rs+web/: asset e markup della WebPage servita dal backend.src/backend.rs: implementazione demo del servizio host che esegue i comandi locali.src/models.rs: payload e modelli condivisi tra frontend e backend.ui/app.slint: layout, proprietà e callback della GUI nativa.build.rs: compilazione della UI Slint durante la build.
rustccargo- toolchain Rust stabile recente
cargo build --release
cargo runsudo apt update
sudo apt install -y build-essential curlcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
rustup update stablerustc --version
cargo --version- La GUI usa
slint::include_modules!()per importare il codice generato dabuild.rs. - La comunicazione HTTP è volutamente minimale e non usa framework esterni.
- Il backend locale usa file in
/tmpper simulare effetti persistenti senza toccare configurazioni reali di sistema, tranne quando si invoca il salvataggio dell'orario contimedatectl. - La WebPage e la GUI nativa sono due front-end distinti, ma condividono la stessa logica di backend e lo stesso perimetro funzionale.