Claude Code no homelab: as regras que dou antes de ele mexer

As regras que dou ao Claude Code no homelab: fora do host Proxmox, segredos em .env 600, nada externo sem ok. CLAUDE.md é pedido; deny no settings é trava.

Publicado
Leitura
7 min
Neste post

Uso o Claude Code nos containers do homelab, até pelo celular, como contei no post sobre tmux, /resume e /remote-control. Uma ferramenta que roda comando sozinha dentro do servidor pede regras claras. Sem elas, é questão de tempo até ela fazer exatamente o que você pediu, e não o que você queria.

Neste post conto as regras que dou para a IA no meu homelab e onde cada uma deve ficar, com o que diz a documentação oficial do Claude Code. A parte mais importante: há regra que é só pedido e regra que é bloqueio de verdade.

Onde ele pode entrar #

A primeira regra não é texto, é acesso. No meu homelab, o Claude Code trabalha nos containers de serviço e nas aplicações, mas não no host Proxmox.

O motivo é simples: o host é a única peça que derruba tudo de uma vez. Um comando errado num container afeta um serviço. No host, afeta todos. Se preciso mexer no Proxmox, eu mesmo faço.

Essa regra não depende de a IA obedecer. Ela não tem como entrar onde não tem acesso. É a camada mais forte que existe.

As três regras que repito #

Dentro dos containers, três regras aparecem em todas as minhas sessões:

  1. Segredos ficam em /etc/<app>/*.env, com permissão 600. Nunca no repositório, nunca em log. Chave de API, senha de SMTP, token: tudo nesse padrão.
  2. Nada externo e nenhum gasto sem a minha confirmação. Publicar, enviar mensagem, criar recurso em nuvem ou qualquer coisa que custe dinheiro passa por mim antes.
  3. Não mexer em produção sem pedir. Alguns containers rodam apps que outras pessoas usam. Nesses, nada muda sem eu dizer.

Elas parecem óbvias, e são. O problema é que uma IA que quer resolver a tarefa encontra o caminho mais curto, e o caminho mais curto às vezes é colar a senha direto no código ou reiniciar o serviço de produção para testar.

O lugar das regras: CLAUDE.md #

Repetir as mesmas regras toda sessão cansa e falha no dia em que eu esqueço. Para isso existe o CLAUDE.md, um arquivo de instruções que o Claude Code carrega no começo de toda sessão. Pela documentação, ele pode ficar em dois níveis:

ArquivoVale para
~/.claude/CLAUDE.mdTodos os projetos daquele usuário
./CLAUDE.md ou ./.claude/CLAUDE.mdSó aquele projeto, e vai para o git junto

As três regras acima são do tipo que vale para tudo, então o lugar delas é o arquivo do usuário. Regras de um app específico (como rodar os testes, onde fica a configuração) vão no CLAUDE.md do projeto.

Um exemplo enxuto:

# Regras do homelab

- Segredos só em /etc/<app>/*.env com chmod 600. Nunca no repositório nem em log.
- Nada externo (publicar, enviar, criar recurso em nuvem) nem gasto sem minha confirmação.
- Não mexer em produção sem eu pedir.

Algumas dicas da documentação:

  • o comando /init gera um CLAUDE.md inicial analisando o projeto;
  • o /memory mostra quais arquivos de memória existem e abre cada um para editar;
  • o /context mostra quais arquivos foram carregados na sessão;
  • o ideal é ficar abaixo de 200 linhas por arquivo. Arquivo longo ocupa mais contexto e é seguido com menos consistência.

CLAUDE.md é pedido, não trava #

Essa é a parte que mais gente não sabe. A documentação diz com todas as letras: o Claude trata o CLAUDE.md como contexto, não como configuração obrigatória. Instrução clara e curta é seguida com muito mais consistência, mas continua sendo instrução.

Para bloquear de verdade, o caminho são as regras de permissão, que o próprio Claude Code aplica, não o modelo. Elas ficam no settings.json, em três listas: allow, ask e deny. A ordem de avaliação é sempre deny, depois ask, depois allow, e uma regra allow não abre exceção numa deny.

Um exemplo no formato da documentação:

{
  "permissions": {
    "deny": [
      "Bash(git push *)",
      "Read(./.env)",
      "Read(./secrets/**)"
    ]
  }
}

Com isso, as ferramentas do Claude Code não abrem o .env nem a pasta secrets, e o git push escrito do jeito que o Claude costuma escrever é recusado. Esse “do jeito que ele costuma escrever” faz diferença, e é o assunto da próxima seção.

O comando /permissions mostra todas as regras ativas e de qual arquivo cada uma veio.

Onde o deny tem furo, e o sandbox fecha #

Seção acrescentada em 30/10/2026. Depois que publiquei este post, o @plugandship comentou no TabNews dois furos nessas regras. Fui conferir na documentação, e ele tem razão nos dois.

Regra de Bash casa com o texto do comando, não com o programa. Pela documentação, um deny de Bash pega a forma que o Claude costuma escrever, mas não o mesmo programa chamado de outro jeito. O Bash(git push *) bloqueia git push, mas não /usr/bin/git push nem sh -c 'git push'. A própria documentação diz que essa regra não é uma fronteira de segurança em volta do programa.

Regra de Read não segura subprocesso. Ela vale para as ferramentas do Claude Code e para os comandos de arquivo que ele reconhece no Bash, como cat, head e sed. Um script Python ou Node que abre o arquivo por conta própria passa direto.

Para os dois casos, a documentação indica o sandbox do Bash. Ele vem desligado: liga com /sandbox na sessão ou com sandbox.enabled no settings.json. A diferença é que ele age no sistema operacional e vale para o comando e para todo processo que o comando abrir. Um Python tentando ler o .env bate na mesma parede. No Linux, ele depende dos pacotes bubblewrap e socat.

O detalhe que pega: por padrão, o sandbox deixa ler quase o computador inteiro, inclusive ~/.ssh e ~/.aws/credentials. O que deve ficar de fora precisa estar listado no denyRead:

{
  "sandbox": {
    "enabled": true,
    "allowUnsandboxedCommands": false,
    "filesystem": {
      "denyRead": ["~/.ssh", "~/.aws", "~/**/.env", "/etc/meuapp"]
    }
  }
}

Duas coisas nesse exemplo valem explicação:

  • allowUnsandboxedCommands: false: quando um comando falha dentro do sandbox, o Claude pode tentar de novo fora dele. Com essa opção desligada, essa saída deixa de existir.
  • Rede: no sandbox, a conexão passa por um proxy que só libera os domínios permitidos, e a lista começa vazia. Um host fora dela gera um pedido de permissão (no modo dontAsk, é recusado). Ou seja, um push para o GitHub de dentro do sandbox não sai sem você liberar o github.com.

E para o push, a conclusão do @plugandship é a mais sólida de todas: não deixar no container nenhuma credencial com permissão de escrita no repositório, ou usar uma deploy key só de leitura. Regra pode ter furo. Credencial que não existe, não.

Como as camadas se somam #

No fim, a segurança vem de várias camadas, da mais fraca para a mais forte:

  1. CLAUDE.md: diz o que eu espero. Cobre o dia a dia.
  2. Permissões no settings.json: recusam as ferramentas do Claude e os comandos do jeito que ele costuma escrever, mesmo que a IA tente.
  3. Sandbox do Bash: vale no sistema operacional, para o comando e para os processos que ele abre. Só bloqueia o que estiver listado.
  4. Permissão de arquivo e usuário no Linux: o 600 no .env e serviços rodando com usuário próprio.
  5. Acesso: o que a IA não alcança, ela não estraga. É por isso que o host Proxmox fica de fora, e é por isso que credencial de escrita não deveria estar no container.

E por baixo de tudo, o que me salvou da última vez: git e backup. Quando perdi tudo, as aplicações voltaram porque reconstruí o código com a IA, como contei no post sobre como a IA me ajudou a reconstruir o homelab. Hoje todo projeto tem repositório no GitHub e deploy por runner self-hosted. Se algo der errado, volto para o último commit.

Resumindo #

  • Limite o acesso primeiro. Aqui, o Claude Code não entra no host Proxmox.
  • Três regras fixas: segredos em /etc/<app>/*.env com 600, nada externo nem gasto sem confirmação, produção só com pedido.
  • CLAUDE.md do usuário para regras gerais, do projeto para regras do app. Curto, abaixo de 200 linhas.
  • CLAUDE.md é contexto. O deny no settings.json trava as ferramentas do Claude, mas no Bash ele casa com o texto do comando.
  • Para valer no sistema, sandbox com denyRead listando o que fica de fora e allowUnsandboxedCommands: false.
  • Git e backup são a última camada.

A IA ajuda muito no homelab. Mas quem decide até onde ela vai sou eu, e essa decisão fica escrita em mais de um lugar.

Fontes e documentação