Scripts de startup
os.startup_scripts cria trabalho one-shot systemd limitado para a imagem resultante. Cada entrada declara comando shell, pacotes necessários, usuário de execução e unit de ordenação.
Scripts de startup são código com capacidade root, a menos que run_as diga o contrário. Devem receber a mesma revisão que qualquer script de instalação.
Formato canônico
{
"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"
}
]
}
}Os campos são description e command, não o campo legado script. run_as e after também usam snake_case. after é uma string de unit systemd, não array.
O schema aceita no máximo 32 entradas e tamanho de comando limitado. A validação rejeita comandos vazios e bytes NUL, mas não torna conteúdo shell seguro ou idempotente.
Projete para retries e falha parcial
Um boot pode ser interrompido depois que alguns efeitos colaterais ocorreram. Escreva scripts para que outra invocação complete com segurança ou saia com estado claro e inspecionável.
Bons padrões incluem:
- escrever em arquivo temporário, verificar e renomear atomicamente;
- verificar se usuários, diretórios ou entradas de configuração já existem;
- usar
installpara owner e mode explícitos; - aplicar
set -Eeuo pipefaile tratar resultados nonzero esperados de forma deliberada; - usar timeouts de rede limitados e contagem finita de retries; e
- escrever marcador de readiness só depois que todos os passos necessários succeedem.
Não dependa de sleep como verificação de readiness. Sonda a dependência real.
Downloads externos
Evite curl ... | sh. Se o first boot precisar buscar artefato:
- use HTTPS com verificação de certificado;
- fixe a versão esperada do artefato ou origem;
- verifique digest criptográfico ou assinatura aprovada antes da execução;
- defina timeouts de connect e total;
- falhe fechado se a verificação falhar; e
- evite logar credenciais ou URLs assinadas.
Para comportamento offline ou reproduzível de fato, inclua conteúdo revisado na imagem ou repositório de pacotes aprovado em vez de baixar no first boot.
Segredos
Nunca embuta credenciais em texto claro na receita, comando, URL ou marcador gerado. JSON da receita e logs de build são evidência retida e podem ser visíveis a operadores. Use mecanismo aprovado de enrollment ou entrega de segredo na hora do deployment e escopo a credencial resultante ao alvo.
Identidade de execução
Prefira conta de serviço sem privilégio. Se root for necessário, reduza o comando ao menor passo privilegiado e defina ownership explícito de arquivo. Confirme que run_as nomeia conta criada antes da unit iniciar.
Verificação
Teste resultados, não só exit status da unit:
{
"type": "file_contains",
"description": "The startup unit wrote its readiness marker.",
"params": {
"path": "/var/lib/example/build-ready",
"content": "ready"
}
}Teste também segundo boot, dependência indisponível e recovery de first run interrompido. Inspecione systemctl status e journal da unit em falha.