
Segredos não pertencem a arquivos de configuração
O problema
Aplicações não deveriam exigir senhas, API keys ou tokens em seus arquivos de configuração. Configuração descreve comportamento e pertence ao git, code review e máquinas de desenvolvedores. Segredos concedem autoridade e precisam de acesso restrito e rotação independente. Colocar ambos no mesmo arquivo acopla ciclos de vida e públicos diferentes.
Evidência no NixOS
Uma auditoria de todos os 445 módulos do NixOS que lidam com segredos reais (no commit 141f212 do nixpkgs) revelou a distribuição de onde o valor secreto acaba:
| Destino | Módulos | Percentual |
|---|---|---|
| Mesclado em arquivo de config em runtime | 110 | 25% |
| Inlined em config no /nix/store | 42 | 9% |
| Variável de ambiente | 161 | 36% |
| Arquivo dedicado aberto pela app | 58 | 13% |
| Credenciais systemd | 53 | 12% |
| Argumento de linha de comando | 19 | 4% |
O número relevante é 110: um quarto dos módulos recupera o segredo com segurança e depois o copia para dentro da configuração porque é a única interface que a aplicação aceita. Usam envsubst, replace-secret, jq, yq, sed ou código custom para montar um arquivo restrito no startup. O resultado pode ser seguro, mas cada módulo passa a possuir glue de segurança específico da aplicação.
O mesmo padrão aparece em outras plataformas como entrypoint scripts, templates Helm, init containers ou etapas de interpolação em CI.
O princípio
Aplicações devem aceitar segredos por um canal dedicado em runtime: password_file, token_file, credenciais systemd, variável de ambiente com escopo estreito ou um provider externo. A separação garante que o deployer não precise fabricar uma segunda versão da configuração contendo segredos.
O caso do Cachix
O Cachix historicamente armazenava auth token e signing keys em ~/.config/cachix/cachix.dhall, junto com nomes de cache e outra configuração. Não era possível compartilhar a configuração de cache sem também compartilhar credenciais.
O devenv 2.2 separa o token via SecretSpec: o projeto declara CACHIX_AUTH_TOKEN, o devenv resolve do provider configurado e o valor é passado ao Cachix sem entrar na configuração. Um PR aberto (Cachix #737) traz a mesma separação para o cliente via SDK Haskell do SecretSpec, resolvendo CACHIX_AUTH_TOKEN e CACHIX_SIGNING_KEY do provider escolhido pelo usuário.
SecretSpec
O SecretSpec resolve isso com um arquivo secretspec.toml que declara o que a aplicação precisa, sem armazenar valores. Providers decidem onde os valores vivem: keyring do sistema para desenvolvimento local, variáveis de ambiente para CI, 1Password/Vault/cloud secret manager para produção - sem mudar a declaração.
SDKs existem para Rust, Python, Go, Ruby, Node.js/TypeScript, Haskell, PHP e C#, compartilhando o mesmo resolver para comportamento consistente entre linguagens.
Recomendação
Se você mantém uma aplicação, pare de adicionar senhas e tokens em schemas de configuração comuns. Aceite referência a arquivo, credencial, variável de ambiente ou provider. Para NixOS, a issue #65 do SecretSpec rastreia uma integração oficial que eliminaria o glue de substituição por módulo.