Como configurar variáveis de ambiente corretamente
1. Fundamentos das variáveis de ambiente
Variáveis de ambiente são pares chave-valor disponíveis no contexto de execução de processos em um sistema operacional. Elas funcionam como um mecanismo fundamental de configuração externa, permitindo que aplicações se comportem de maneira diferente sem alteração de código-fonte.
A distinção entre os tipos de variáveis é crucial:
- Variáveis de ambiente: definidas no sistema operacional, herdadas por processos filhos. Exemplo:
PATH,HOME - Variáveis de shell: específicas do interpretador de comandos (bash, zsh), não exportadas automaticamente
- Variáveis de aplicação: internas ao código, definidas e gerenciadas pelo próprio programa
O ciclo de vida segue uma hierarquia clara:
# Definição no shell atual (não exportada)
DB_HOST=localhost
# Exportação para processos filhos
export DB_HOST=localhost
# Herança: processos filhos recebem variáveis exportadas
./meu_script.sh # herda DB_HOST
# Escopo de sessão: definido em .bashrc, .profile
echo 'export APP_ENV=production' >> ~/.bashrc
2. Estruturação e nomenclatura de variáveis
Padrões de nomenclatura garantem clareza e manutenibilidade:
# Padrão recomendado: MAIÚSCULAS com underscores
APP_NAME=meu_projeto
APP_VERSION=2.1.0
DB_HOST=localhost
DB_PORT=5432
API_BASE_URL=https://api.exemplo.com
SECRET_API_KEY=abc123def456
Organização hierárquica por prefixos:
# Variáveis globais (sistema)
LANG=pt_BR.UTF-8
TZ=America/Sao_Paulo
# Variáveis de projeto (prefira APP_)
APP_DEBUG=true
APP_LOG_LEVEL=info
APP_CACHE_DRIVER=redis
# Variáveis de módulo específico
DB_CONNECTION=pgsql
DB_DATABASE=meubanco
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
# Variáveis de segurança
SECRET_JWT_KEY=minha_chave_jwt
SECRET_ENCRYPTION_KEY=chave_cripto
3. Fontes e hierarquia de carregamento
A ordem de precedência (do menor para o maior poder de sobrescrita):
1. Sistema (/etc/environment, systemd)
2. Shell (~/.bashrc, ~/.profile)
3. Arquivo .env (projeto)
4. Comando inline (APP_ENV=dev node app.js)
Carregamento automático com ferramentas modernas:
# .env.example (versionado)
APP_ENV=development
APP_DEBUG=true
DB_HOST=localhost
DB_PORT=5432
# .env (ignorado pelo git)
APP_ENV=production
APP_DEBUG=false
DB_HOST=10.0.0.50
DB_PORT=5432
# .gitignore
.env
*.local
Uso de direnv para carregamento por diretório:
# .envrc (no diretório do projeto)
export APP_ENV=development
export DB_HOST=localhost
export SECRET_KEY=$(cat .secret_key)
# Permissão (uma vez)
direnv allow .
4. Tratamento de dados sensíveis e secrets
Nunca armazene segredos diretamente em variáveis de ambiente versionadas:
# CORRETO: .env.example (versionado, sem valores reais)
DB_PASSWORD=
API_KEY=
SECRET_TOKEN=
# CORRETO: .env (ignorado pelo git, com valores reais)
DB_PASSWORD=s3nh4f0rt3
API_KEY=ak_123456789
SECRET_TOKEN=st_abcdef123
# .gitignore
.env
*.key
*.pem
secrets/
Para ambientes críticos, use cofres de segredos:
# Exemplo com Vault (conceitual)
vault kv put secret/minhaapp DB_PASSWORD=s3nh4f0rt3
# Exemplo com 1Password CLI
op run -- node app.js
Proteção contra vazamento em logs:
# Em código (exemplo Python)
import os
import re
def get_env_safe(key):
value = os.getenv(key)
if key.startswith('SECRET_') or key.startswith('DB_PASSWORD'):
return value[:4] + '****' if value else None
return value
# Log seguro
print(f"Config: DB_HOST={get_env_safe('DB_HOST')}")
print(f"Config: DB_PASSWORD={get_env_safe('DB_PASSWORD')}")
5. Configuração por ambiente (dev, staging, prod)
Estrutura de arquivos por ambiente:
# .env.dev
APP_ENV=development
APP_DEBUG=true
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=app_dev
# .env.staging
APP_ENV=staging
APP_DEBUG=false
DB_HOST=staging-db.internal
DB_PORT=5432
DB_DATABASE=app_staging
# .env.prod
APP_ENV=production
APP_DEBUG=false
DB_HOST=prod-db.internal
DB_PORT=5432
DB_DATABASE=app_prod
Mecanismo de fallback com validação:
# Script de carregamento (exemplo shell)
#!/bin/bash
load_env() {
local env_file=".env.${APP_ENV:-dev}"
if [ -f "$env_file" ]; then
set -a
source "$env_file"
set +a
elif [ -f ".env" ]; then
set -a
source ".env"
set +a
fi
# Validação de obrigatórias
local required_vars=("DB_HOST" "DB_PASSWORD" "API_KEY")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "ERRO: Variável $var não definida para ambiente $APP_ENV"
exit 1
fi
done
}
load_env
6. Boas práticas de versionamento e deploy
Versionamento de esquemas:
# .env.example (versionado)
APP_ENV=
APP_DEBUG=
DB_HOST=
DB_PORT=5432
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
API_KEY=
# schema.json (para validação automatizada)
{
"required": ["DB_HOST", "DB_PASSWORD", "API_KEY"],
"types": {
"APP_DEBUG": "boolean",
"DB_PORT": "integer",
"APP_ENV": {"enum": ["dev", "staging", "prod"]}
}
}
Integração com CI/CD:
# .github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configurar variáveis
run: |
echo "APP_ENV=production" >> $GITHUB_ENV
echo "DB_HOST=${{ secrets.DB_HOST }}" >> $GITHUB_ENV
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> $GITHUB_ENV
- name: Deploy
run: ./deploy.sh
Imutabilidade em containers:
# Dockerfile
FROM node:18-alpine
ENV APP_ENV=production
ENV NODE_ENV=production
COPY .env.prod /app/.env
CMD ["node", "app.js"]
# docker-compose.yml
services:
app:
image: minhaapp:1.0
environment:
- DB_HOST=db.internal
- DB_PASSWORD=${DB_PASSWORD}
env_file:
- .env.prod
7. Debug, logging e monitoramento de variáveis
Técnicas de inspeção segura:
# Listar variáveis sem segredos (shell)
env | grep -v -E '(PASSWORD|SECRET|KEY|TOKEN)' | sort
# Mascaramento em logs (exemplo Node.js)
const sensitiveKeys = ['PASSWORD', 'SECRET', 'KEY', 'TOKEN'];
function maskEnv(env) {
const masked = {};
for (const [key, value] of Object.entries(env)) {
if (sensitiveKeys.some(sk => key.includes(sk))) {
masked[key] = value.slice(0, 4) + '****';
} else {
masked[key] = value;
}
}
return masked;
}
console.log('Config:', JSON.stringify(maskEnv(process.env), null, 2));
Ferramentas de diagnóstico:
# Diagnóstico completo
echo "=== Variáveis de Ambiente ==="
env | sort
# Verificar variável específica
echo "DB_HOST está definido: $(env | grep -c DB_HOST)"
# Usar envsubst para template
echo "Conectando em ${DB_HOST}:${DB_PORT}" | envsubst
# Dashboard de configuração (conceitual)
# curl http://localhost:3000/config?token=admin_token
Referências
- Documentação oficial: Variáveis de ambiente no Linux (archlinux.org) — Guia completo sobre definição, exportação e gerenciamento de variáveis de ambiente em sistemas Linux
- 12 Factor App: Configuração — Artigo seminal sobre armazenamento de configuração em variáveis de ambiente como prática de desenvolvimento de aplicações
- dotenv (npm) — Biblioteca mais popular para carregamento de variáveis de ambiente a partir de arquivos .env em Node.js
- direnv: Gerenciamento de variáveis por diretório — Ferramenta que carrega e descarrega variáveis de ambiente automaticamente ao navegar entre diretórios
- HashiCorp Vault: Gerenciamento de segredos — Solução corporativa para armazenamento e acesso seguro a segredos, incluindo variáveis de ambiente dinâmicas
- OWASP: Armazenamento seguro de senhas e chaves — Guia de segurança para armazenamento de credenciais, incluindo boas práticas com variáveis de ambiente
- GitHub Actions: Usando variáveis de ambiente e segredos — Documentação oficial sobre injeção segura de variáveis em pipelines CI/CD