Secrets obrigatórios não resolvidos
O deploy para quando uma chave listada em required: não chega ao ambiente
final do container. Isso é proposital: subir uma app sem credencial
reportando sucesso é pior do que não subir.
A partir da v2.69.0 a mensagem diz onde o runner procurou o bundle.
O sintoma
secrets_not_materialized: 2 secret(s) obrigatório(s) em `required:`
(["DB_PASSWORD", "API_KEY"]) NÃO foram resolvidos — nenhum chegou ao ambiente
final do container (nem em runtime.env, nem em .env/.secrets).
Deploy interrompido: melhor parar do que subir uma app sem credencial
reportando verde.
Um bundle de secrets existe, mas nenhum valor para as chaves acima veio dele.
Verifique o conteúdo do que está marcado abaixo:
- /data/apps/minha-app/.runner/secrets.production.tester.enc (namespace do servidor (`target:` no config.yml))
- /data/apps/minha-app/.runner/secrets.production.enc (instância) <- existe
- /data/apps/minha-app/.runner/secrets.enc (legado (bundle único)) <- existe
Preencha: runner env set <app> <KEY> <VALOR> (use --secret para valor sensível)Uma mensagem equivalente aparece como missing_required quando as chaves
existem no ambiente porém vazias. Ambas listam os mesmos candidatos.
Como ler a lista
Os caminhos aparecem na ordem em que o runner os consulta, do mais
específico para o mais genérico. Cada linha traz a origem entre parênteses, e
<- existe marca os que estão no disco.
| Origem | Quando é usado |
|---|---|
| namespace do servidor | Há target: no config.yml — separa bundles por servidor |
| instância | Bundle por instância (production, staging, ...) |
| legado (bundle único) | Formato antigo, um bundle para todas as instâncias |
O cabeçalho diz o que foi verificado, e muda a conduta:
- "Um bundle de secrets existe..." → o arquivo está lá; o problema é o conteúdo. Não perca tempo procurando arquivo.
- "Nenhum bundle de secrets foi encontrado..." → nenhum candidato existe; o problema é o arquivo ausente.
Correção
Caso 1 — o bundle existe mas não tem a chave
O mais comum: a chave foi acrescentada ao required: e ninguém preencheu o
valor.
runner env set minha-app DB_PASSWORD 'valor' --secret
runner deploy minha-appPara conferir quais chaves já estão no bundle sem decifrar valores:
runner env list minha-appIsso funciona em bundles de ckey assimétrica, onde os nomes ficam legíveis e só os valores são selados. Em bundle de ckey simétrica (o padrão atual) o arquivo é um blob opaco e não há como listar chaves sem a ckey — ver ckey simétrica e assimétrica.
Caso 2 — nenhum bundle existe
App nova, ou bundle perdido na migração de servidor. Preencher as chaves cria o bundle:
runner env set minha-app DB_PASSWORD 'valor' --secret
runner env set minha-app API_KEY 'valor' --secretSe o bundle deveria existir e sumiu, veja Restaurar em novo servidor.
Caso 3 — o bundle existe mas não abre
Se a mensagem for de falha ao decifrar (e não de valor ausente), o problema é a ckey, não o preenchimento. Veja Bundle decrypt failed.
Caso 4 — a chave não é obrigatória de verdade
Se ela pode faltar legitimamente, tire-a de required:. Declarar em secrets:
já a mantém cifrada sem exigir valor:
secrets:
ANALYTICS_TOKEN: "" # cifrado, opcional
instances:
production:
required:
- DB_PASSWORD # este sim bloqueia o deploy se faltarBypass pontual
Para um deploy meio-configurado, com consciência do risco:
runner deploy minha-app --allow-missing-requiredNão use isso em produção como rotina. O gate existe porque app sem credencial costuma falhar mais tarde, de forma mais confusa.
Quando o gate NÃO dispara
Não há gate de secret sem required: declarado. Uma instância com
required: [] substitui a lista da base por vazio e passa limpo — enquanto
required: ausente herda a lista da base.
instances:
staging:
required: [] # nenhum obrigatório aqui
production:
# ausente → herda o required: da baseVer também
- Bundle decrypt failed — quando o bundle não abre
- Hierarquia de env e secrets — quem vence quem
- Secrets por instância — bundles separados