Colou a chave da API direto no PHP pra testar, esqueceu, commitou. Antes de qualquer git: revogue a chave no painel do provedor e gere outra. Limpar histórico depois é higiene, quem fecha a porta é a revogação.
Tirando a chave do código
A chave vai pra variável de ambiente. Em servidor com php-fpm eu declaro no pool, que fica fora do projeto e fora do Git:
# /etc/php/8.3/fpm/pool.d/www.conf
env[IA_API_KEY] = "chave-nova-aqui"
# e no PHP
$chave = getenv('IA_API_KEY');
if ($chave === false || $chave === '') {
throw new RuntimeException('IA_API_KEY não configurada');
}
Mexeu no pool, rode systemctl reload php8.3-fpm. Sem o reload os workers antigos continuam sem a variável e o getenv volta false em parte das requisições.
Se preferir arquivo .env com vlucas/phpdotenv, atenção num detalhe que derruba muita gente: createImmutable popula $_ENV e $_SERVER, mas não alimenta getenv(). Ou você lê por $_ENV[‘IA_API_KEY’], ou usa createUnsafeImmutable. Eu fico no $_ENV.
Bloqueando o arquivo e o commit
Coloque .env no .gitignore antes de criar o arquivo, e trave o acesso pela web no nginx, porque .env dentro da raiz pública é servido como texto puro se ninguém barrar:
location ~ /.(?!well-known).* {
deny all;
}
Location de regex o nginx avalia na ordem em que aparece no arquivo, então deixe esse bloco acima do location ~ .php$ do site. Depois nginx -t e systemctl reload nginx, e teste chamando /.env no navegador: tem que voltar 403.
Sobre o histórico: git rm –cached .env só para de versionar dali pra frente, o blob antigo continua em todo clone, em cada fork e no cache do provedor. Reescrever com git filter-repo ajuda no repositório privado da equipe, mas troca todos os hashes e exige force-push combinado com quem trabalha ali. Trate a chave antiga como pública para sempre.
Guarde um .env.example com os nomes das variáveis e valores em branco. Quem clona já sabe o que precisa preencher sem ter que te perguntar.