Truques para criar arquivos de configuração dinâmicos com envsubst
1. Introdução ao envsubst e substituição de variáveis
O envsubst é uma ferramenta presente no pacote gettext do Linux que permite substituir variáveis de ambiente em arquivos de texto de forma simples e eficiente. Diferentemente de ferramentas como sed ou awk, que exigem expressões regulares complexas, o envsubst trabalha diretamente com o formato padrão de variáveis do shell ($VAR e ${VAR}), tornando o processo mais intuitivo e menos propenso a erros.
A sintaxe básica é direta:
envsubst < template.txt > config.txt
Este comando lê o arquivo template.txt, substitui todas as variáveis de ambiente encontradas pelos seus valores atuais e escreve o resultado em config.txt. O comportamento padrão é substituir todas as variáveis no formato $VAR e ${VAR}.
2. Preparação de templates para substituição
Para criar templates eficientes, utilize placeholders claros e consistentes. A estrutura básica de um template pode ser:
# template.conf
DATABASE_HOST=$DB_HOST
DATABASE_PORT=${DB_PORT}
DATABASE_USER=$DB_USER
DATABASE_PASSWORD=${DB_PASSWORD}
LOG_LEVEL=${LOG_LEVEL:-info}
Note que é possível definir valores padrão usando a sintaxe ${VAR:-default}. Isso garante que, mesmo que a variável de ambiente não esteja definida, o template terá um valor funcional.
Para evitar conflitos com caracteres especiais, lembre-se:
- O cifrão ($) sempre inicia uma variável
- Use aspas simples para evitar expansão acidental no shell
- Barras invertidas (\) podem escapar caracteres em alguns contextos
3. Controle granular com a opção SHELL-FORMAT
Uma das funcionalidades mais poderosas do envsubst é a capacidade de filtrar quais variáveis serão substituídas usando a opção SHELL-FORMAT:
envsubst '$DB_HOST $DB_PORT' < template.conf > config.conf
Neste exemplo, apenas $DB_HOST e $DB_PORT serão substituídos. Todas as outras variáveis (como $PATH ou $HOME) permanecerão literais no arquivo de saída. Isso é crucial quando seu template contém variáveis que não devem ser expandidas.
Exemplo prático para um arquivo de configuração de banco:
# template_db.conf
[Database]
Host=$DB_HOST
Port=${DB_PORT}
User=admin
Password=${DB_PASSWORD}
Path=$PATH
export DB_HOST=localhost
export DB_PORT=5432
envsubst '$DB_HOST $DB_PORT' < template_db.conf > db.conf
O resultado manterá ${DB_PASSWORD} e $PATH como literais.
4. Combinando envsubst com arquivos .env e export
Para projetos maiores, é comum utilizar arquivos .env para gerenciar variáveis. A combinação com envsubst é poderosa:
# Carregar variáveis do .env, ignorando comentários
export $(grep -v '^#' .env | xargs)
# Gerar configuração
envsubst < template.conf > config.conf
Uma abordagem mais robusta usando set -a:
set -a
source .env
set +a
envsubst < template.conf > config.conf
O comando set -a faz com que todas as variáveis atribuídas sejam automaticamente exportadas para o ambiente, eliminando a necessidade de export manual para cada variável.
5. Geração de múltiplos arquivos a partir de um único template
Um dos cenários mais úteis é gerar configurações para diferentes ambientes a partir de um template único:
# Template: template.yml
app:
name: $APP_NAME
version: ${APP_VERSION:-1.0.0}
environment: $ENV
database:
host: $DB_HOST
port: ${DB_PORT:-5432}
Arquivos de ambiente:
# dev.env
APP_NAME=myapp-dev
APP_VERSION=2.0.0-beta
ENV=development
DB_HOST=localhost
DB_PORT=5432
# prod.env
APP_NAME=myapp
ENV=production
DB_HOST=db.prod.example.com
Gerando as configurações:
for env in dev prod; do
set -a
source "$env.env"
set +a
envsubst < template.yml > "${env}.yml"
done
6. Tratamento de variáveis aninhadas e valores complexos
Ao trabalhar com JSON e YAML, é necessário cuidado especial com aspas e caracteres de escape:
# template.json
{
"service": {
"name": "$SERVICE_NAME",
"host": "${SERVICE_HOST}",
"config": "${SERVICE_CONFIG}"
}
}
Para valores contendo espaços ou caracteres especiais, use aspas duplas no template:
export SERVICE_CONFIG='{"timeout": 30, "retries": 3}'
envsubst < template.json > config.json
A dica de usar ${VAR:-default} é especialmente útil para evitar falhas quando variáveis não estão definidas:
export DB_HOST=${DB_HOST:-localhost}
export DB_PORT=${DB_PORT:-3306}
7. Integração com Docker e containers
O envsubst é amplamente utilizado em imagens Docker para gerar configurações em tempo de execução. Um exemplo clássico com Nginx:
# entrypoint.sh
#!/bin/bash
set -e
# Gerar configuração do Nginx
envsubst '$NGINX_HOST $NGINX_PORT' < /etc/nginx/nginx.template > /etc/nginx/nginx.conf
# Limpar variáveis sensíveis após uso
unset NGINX_HOST NGINX_PORT
# Iniciar Nginx
exec nginx -g 'daemon off;'
No Dockerfile:
COPY nginx.template /etc/nginx/nginx.template
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Boas práticas importantes:
- Sempre limpe variáveis sensíveis após a substituição
- Use exec no final para garantir que o processo principal receba sinais corretamente
- Mantenha templates versionados e arquivos gerados no .gitignore
8. Depuração e boas práticas
Para verificar se todas as variáveis foram substituídas corretamente:
# Verificar variáveis não substituídas
grep '\$' config_saida.conf
# Usar set -u para evitar substituições silenciosas
set -u
envsubst < template.conf > config.conf
O comando set -u faz com que o shell interrompa a execução se encontrar uma variável não definida, evitando substituições silenciosas por strings vazias.
Versionamento de templates:
# .gitignore
*.conf
!*.template
Mantenha apenas os templates no versionamento e gere os arquivos de configuração durante o deployment. Isso garante que as configurações específicas de cada ambiente não poluam o repositório.
Referências
- GNU gettext documentation - envsubst — Documentação oficial do GNU gettext com detalhes sobre todas as opções do envsubst
- Using envsubst for configuration management in Docker — Guia oficial do Docker sobre boas práticas com entrypoints e envsubst
- envsubst: The Swiss Army Knife for Environment Variable Substitution — Tutorial prático do Linux Handbook com exemplos avançados de uso do envsubst
- Environment Variables in Nginx with envsubst — Artigo da Nginx Inc. sobre integração de variáveis de ambiente com envsubst
- 12 Factor App - Configuration — Documentação do método 12 Factor App sobre gerenciamento de configuração através de variáveis de ambiente
- Bash set builtin command — Documentação oficial do Bash sobre o comando set e suas opções para controle de variáveis