Script di avvio
os.startup_scripts crea lavoro systemd one-shot delimitato per l’immagine
risultante. Ogni voce dichiara un comando shell, pacchetti richiesti, utente di
esecuzione e unit di ordinamento.
Gli script di avvio sono codice con capacità root salvo diversa indicazione in
run_as. Devono ricevere la stessa revisione di qualsiasi script di installazione.
Forma canonica
{
"os": {
"startup_scripts": [
{
"name": "write-build-marker",
"description": "Create a local readiness marker after networking is available.",
"command": "set -Eeuo pipefail\ninstall -d -m 0755 /var/lib/example\nprintf '%s\\n' ready > /var/lib/example/build-ready",
"packages": [],
"run_as": "root",
"after": "network-online.target"
}
]
}
}I campi sono description e command, non il campo legacy script. Anche run_as
e after usano snake_case. after è una stringa unit systemd, non un array.
Lo schema accetta al massimo 32 voci e una dimensione comando delimitata. La validazione rifiuta comandi vuoti e byte NUL, ma non rende sicuro o idempotente il contenuto shell.
Progetta per retry e fallimento parziale
Un boot può essere interrotto dopo che alcuni effetti collaterali sono avvenuti. Scrivi script così che un’altra invocazione completi in sicurezza o esca con uno stato chiaro e ispezionabile.
Buoni pattern includono:
- scrivere su file temporaneo, verificarlo, poi rinominare atomicamente;
- controllare se utenti, directory o voci configurazione esistono già;
- usare
installper owner e mode espliciti; - applicare
set -Eeuo pipefaile gestire risultati nonzero attesi deliberatamente; - usare timeout rete delimitati e un conteggio retry finito; e
- scrivere un marker readiness solo dopo che tutti i passi richiesti riescono.
Non affidarti a sleep come controllo readiness. Sonde la dipendenza reale.
Download esterni
Evita curl ... | sh. Se il first boot deve scaricare un artefatto:
- usa HTTPS con verifica certificato;
- pin la versione artefatto o sorgente attesa;
- verifica un digest crittografico o firma approvata prima dell’esecuzione;
- imposta timeout connect e total;
- fallisci chiuso se la verifica fallisce; e
- evita di loggare credenziali o URL firmati.
Per comportamento davvero offline o riproducibile, includi contenuto revisionato nell’immagine o in un repository pacchetti approvato invece di scaricare al first boot.
Segreti
Non incorporare mai credenziali in chiaro in ricetta, comando, URL o marker generato. JSON ricetta e log build sono evidenza conservata e possono essere visibili agli operatori. Usa un meccanismo enrollment o consegna segreti approvato al deploy e delimita la credenziale risultante al target.
Identità di esecuzione
Preferisci un account servizio non privilegiato. Se serve root, riduci il comando
al passo privilegiato più piccolo e imposta ownership file esplicita. Conferma che
run_as nomini un account creato prima che l’unit parta.
Verifica
Testa esiti piuttosto che solo lo exit status dell’unit:
{
"type": "file_contains",
"description": "The startup unit wrote its readiness marker.",
"params": {
"path": "/var/lib/example/build-ready",
"content": "ready"
}
}Testa anche un secondo boot, una dipendenza non disponibile e recovery da un first
run interrotto. Ispeziona systemctl status e il journal dell’unit in caso di
fallimento.