FNSP Web Page

Variáveis de ambiente: o que pode estar no .env e o que nunca

Há uma ideia generalizada de que pôr um valor numa variável de ambiente é pô-lo em segurança. Não é — é só tirá-lo do código. São coisas diferentes, e a diferença dá disgostos.

1. O caso que mais custa: o que é lido na construção

Este site tem duas variáveis que parecem iguais a todas as outras e não são:

ARG NEXT_PUBLIC_SITE_URL
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL

O prefixo NEXT_PUBLIC_ diz ao Next para substituir aquele valor no momento da construção, dentro do JavaScript que vai ser servido ao browser. Deixa de ser uma variável e passa a ser texto dentro de um ficheiro público.

Daí saem duas consequências que apanham toda a gente uma vez:

  • Pôr essa variável no .env do servidor não faz nada. O valor já está compilado; mudá-lo exige reconstruir a imagem.

  • Pôr lá um segredo é publicá-lo. Qualquer pessoa o lê com o botão direito.

A regra que daí sai vale para qualquer ferramenta com este mecanismo: se o prefixo diz «público», é porque é.

2. O que pode estar no .env

Em desenvolvimento, praticamente tudo — é um ficheiro na máquina de quem programa, com credenciais de uma base que só existe ali.

As duas condições são: nunca é comitado, e nunca entra numa imagem. A primeira é uma linha no .gitignore; a segunda é uma linha no .dockerignore, e a razão está no artigo sobre o contexto de construção — um ficheiro que entre numa camada fica lá para sempre, mesmo que seja apagado a seguir.

O que se comita é o exemplo, com as chaves e sem os valores:

# .env.example — este sim, vai para o repositório
DATABASE_URL=postgres://utilizador:senha@localhost:5432/base
AUTH_SECRET=
AUTH_AUTHENTIK_ID=

Serve de documentação e evita a pergunta «o que é que eu tenho de preencher» a cada pessoa nova.

3. Em produção, o ficheiro não é o sítio ideal

É aceitável, e é o que este site faz: um .env ao lado do compose, lido por env_file, com permissões restritas. Para um servidor pessoal chega bem.

O que convém saber é o que isso tem contra si. Um valor passado como variável de ambiente é legível por quem conseguir ler o processo:

cat /proc/1234/environ | tr '\0' '\n'

E acaba em sítios onde ninguém pensa: no resultado de um docker inspect, no relatório de um erro enviado para uma ferramenta de monitorização, no dump de uma falha. Um cofre a sério — ou os segredos do próprio orquestrador, que chegam como ficheiros e não como variáveis — fecha essa porta.

4. Validar à entrada

Uma variável em falta devolve undefined, e o programa segue com ela. O erro aparece muito depois, longe da causa — uma ligação a undefined, uma assinatura com a palavra undefined.

function obrigatoria(nome) {
  const valor = process.env[nome];
  if (!valor) throw new Error(`Falta a variável ${nome}`);
  return valor;
}

export const BASE = obrigatoria('DATABASE_URL');

Falhar no arranque é muito melhor do que falhar às três da manhã com uma mensagem que não diz nada. Neste site é o que o cliente da base faz: sem DATABASE_URL, rebenta à primeira utilização e diz porquê.

O resumo

Variável de ambiente serve para tirar valores do código e para os mudar sem recompilar. Não é um cofre. O que for lido na construção não é segredo nenhum, o que estiver no ambiente do processo é legível por quem lá chegar, e o que faltar deve impedir o arranque em vez de aparecer como undefined horas depois.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.