Infraestrutura / AGENT SKILLS
Auditoria e otimização de servidor
Audita o servidor onde está rodando, qualquer que seja a stack: descobre SO, init, runtime de containers, proxy, banco, filas e apps antes de analisar, correlaciona métricas e logs, gera relatório priorizado + baseline versionado e aplica correções só com aprovação. Use quando o usuário pedir para analisar/auditar/otimizar o servidor ou a VPS, investigar lentidão, alto uso de CPU/RAM/disco, erros 5xx, crash loop, logs cheios de erro ou saúde geral da máquina.
Instruções da skill
SKILL.md ↗---
name: auditoria-servidor
description: "Audita o servidor onde está rodando, qualquer que seja a stack: descobre SO, init, runtime de containers, proxy, banco, filas e apps antes de analisar, correlaciona métricas e logs, gera relatório priorizado + baseline versionado e aplica correções só com aprovação. Use quando o usuário pedir para analisar/auditar/otimizar o servidor ou a VPS, investigar lentidão, alto uso de CPU/RAM/disco, erros 5xx, crash loop, logs cheios de erro ou saúde geral da máquina."
---
# Auditoria e otimização de servidor
Você roda **dentro** do servidor auditado (Claude Code / Codex no terminal), numa máquina que você não conhece. A stack pode ser qualquer uma: Debian, RHEL, Alpine, Arch; systemd, OpenRC, s6, supervisord ou nada; Docker, Podman, k3s, LXC ou bare metal; nginx, Apache, Caddy, Traefik, HAProxy, OpenLiteSpeed; Postgres, MySQL, MongoDB, SQLite, Redis; Node, PHP, Python, Java, Go, Ruby, .NET.
**Portanto: descobrir vem antes de analisar.** É proibido rodar um comando de diagnóstico de um componente antes de confirmar que ele existe nesta máquina, e é proibido concluir qualquer coisa a partir de um comando que falhou por ausência da ferramenta.
## Regras invioláveis
1. **Fases 0–3 são somente leitura.** Nada de editar config, reiniciar serviço, matar processo, apagar arquivo, instalar pacote ou atualizar sistema antes da Fase 4.
2. **Nada é aplicado sem aprovação explícita**, item por item. Uma aprovação não vale para o resto.
3. **Backup antes de qualquer edição** (`cp arq arq.bak.$(date +%F-%H%M)`), com o comando de rollback entregue junto.
4. **Não reinicie serviço em produção** sem confirmar e sem validar a config antes. Prefira `reload` a `restart`.
5. **Não instale nada** para diagnosticar. Se falta ferramenta, use o que existe (`/proc`, shell puro) e registre a limitação. Instalar só na Fase 4, se aprovado.
6. **Redija segredos.** Ao citar log ou config, mascare senha, token, chave, `DATABASE_URL`, dado pessoal → `***`.
7. Sem `sudo` interativo travando o terminal: use `sudo -n` e, na falha, registre "não verificado (requer root)".
8. Em log grande, sempre limite (`tail -n`, `--since`, `head`). Nunca `cat` num log inteiro.
9. **Nunca invente caminho de log ou de config.** Descubra (Fase 0.4) ou marque como não encontrado.
---
## Fase 0 — Descoberta da stack (obrigatória, somente leitura)
O objetivo é produzir um **perfil da stack** que decide quais módulos da Fase 1 rodam. Nada de análise aqui.
### 0.1 Base do sistema
```bash
cat /etc/os-release 2>/dev/null | head -4; uname -srm
cat /proc/cpuinfo | grep -c ^processor; head -3 /proc/meminfo; uptime
df -hT 2>/dev/null | grep -vE 'tmpfs|devtmpfs'
# gerenciador de pacotes e init (não presuma)
for p in apt dnf yum zypper pacman apk; do command -v $p >/dev/null && echo "pkg=$p"; done
ps -p 1 -o comm= # systemd | init | s6-svscan | runit | supervisord | tini...
```
### 0.2 Estamos dentro de container ou VM?
```bash
systemd-detect-virt 2>/dev/null; grep -qaE 'docker|lxc|kubepods' /proc/1/cgroup && echo "em container"
ls /.dockerenv 2>/dev/null; cat /sys/fs/cgroup/memory.max /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null | head -1
```
Se estamos **dentro** de um container, `free`/`df`/`nproc` mentem: os limites reais estão nos cgroups. Diga isso ao usuário e use os limites de cgroup como referência; a auditoria fica restrita ao container, e recomende rodar também no host se ele tiver acesso.
### 0.3 O que está realmente rodando
A fonte de verdade são os **processos e as portas**, não o `which`.
```bash
ps -eo pid,ppid,user,comm,args --sort=-%mem | head -30
(ss -ltnp || netstat -ltnp) 2>/dev/null | head -30
# supervisão, conforme o init detectado em 0.1
systemctl list-units --type=service --state=running --no-pager 2>/dev/null | head -40
rc-status 2>/dev/null; supervisorctl status 2>/dev/null; pm2 list 2>/dev/null
# runtime de containers / orquestrador
for r in docker podman nerdctl ctr kubectl k3s; do command -v $r >/dev/null && echo "runtime=$r"; done
docker ps --format '{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null || podman ps 2>/dev/null
kubectl get pods -A 2>/dev/null | head -20
crontab -l 2>/dev/null; ls /etc/cron.d 2>/dev/null; systemctl list-timers --no-pager 2>/dev/null | head
```
### 0.4 Onde ficam os logs e as configs (descubra, não presuma)
```bash
# do processo para o arquivo: FDs abertos revelam log e config reais
for pid in <pids dos serviços relevantes>; do ls -l /proc/$pid/fd 2>/dev/null | grep -iE 'log|\.conf'; done
lsof -p <pid> 2>/dev/null | grep -iE 'log|conf'
systemctl cat <serviço> 2>/dev/null | grep -iE 'ExecStart|Environment|StandardOutput'
ls -laShR /var/log 2>/dev/null | head -30 # maiores primeiro
journalctl --disk-usage 2>/dev/null
docker inspect --format '{{.Name}} {{.LogPath}} driver={{.HostConfig.LogConfig.Type}} {{.HostConfig.LogConfig.Config}}' $(docker ps -aq) 2>/dev/null
```
Colete também o diretório da aplicação (cwd do processo: `ls -l /proc/<pid>/cwd`) e procure `docker-compose.yml`, `.env`, `package.json`, `requirements.txt`, `pom.xml`, `go.mod` — eles dizem o que a app é sem precisar adivinhar.
### 0.5 Perfil da stack
Antes de seguir, declare ao usuário em 5–8 linhas: SO e init; se estamos em container e quais limites; recursos reais; papel da máquina; componentes detectados (proxy, banco, cache/fila, runtimes, apps); onde estão os logs; e o que **não** foi possível inspecionar. Esse perfil vira a seção "Stack" do relatório e a chave dos módulos abaixo.
---
## Fase 1 — Coleta modular (só os módulos que o perfil ativou)
### M1 · Recursos e saturação (sempre)
```bash
cat /proc/loadavg; cat /proc/pressure/{cpu,io,memory} 2>/dev/null # PSI: melhor sinal de saturação
vmstat 1 5 2>/dev/null || (cat /proc/stat; sleep 2; cat /proc/stat)
free -m 2>/dev/null || head -5 /proc/meminfo; swapon --show 2>/dev/null; cat /proc/sys/vm/swappiness
ps -eo pid,comm,%cpu,%mem,rss --sort=-%mem | head -15
ps -eo pid,comm,%cpu,%mem --sort=-%cpu | head -15
df -hi 2>/dev/null | grep -vE 'tmpfs' # inodes: "disco cheio" fantasma
du -xh --max-depth=2 / 2>/dev/null | sort -rh | head -20
iostat -x 1 3 2>/dev/null || cat /proc/diskstats | head
dmesg -T --level=err,warn 2>/dev/null | tail -40 # OOM killer, erro de disco/rede
```
### M2 · Camada de supervisão (conforme o init de 0.1)
Procure serviços falhando, reinicializações em loop e unidades mascaradas: `systemctl --failed`, `rc-status --crashed`, `supervisorctl status`, `pm2 list` (coluna restarts), `docker inspect --format '{{.Name}} restarts={{.RestartCount}}'`. **RestartCount alto = crash loop silencioso**, quase sempre um P0/P1 que ninguém viu.
### M3 · Proxy / web server (só o que foi detectado)
Use o teste de config e o dump de config do próprio produto — `nginx -T`, `apachectl -S`, `caddy validate`, `haproxy -c -f`, `traefik healthcheck` — e o log de acesso encontrado em 0.4. Daí extraia: distribuição de status HTTP, top URLs com 5xx, cauda de latência (se o formato de log tiver tempo de resposta), erros de upstream/timeout/handshake, limites de workers e conexões, keepalive, compressão, cache estático, tamanho máximo de body.
```bash
# exemplo para log combinado; ADAPTE os campos ao formato real do arquivo
awk '{c[$9]++} END{for(s in c) print c[s], s}' <access.log> | sort -rn | head
awk '$9 ~ /^5/ {print $7}' <access.log> | sort | uniq -c | sort -rn | head
```
Antes de qualquer `awk` por posição, **olhe 3 linhas do log** e confirme o formato. Formato custom com posições diferentes é a regra, não a exceção.
### M4 · Banco de dados / cache / fila (só o que foi detectado)
Para cada um, colete pelo próprio cliente: parâmetros de memória e conexões vs. RAM real da máquina; conexões em uso vs. máximo; queries lentas; locks/deadlocks; taxa de acerto de cache; erros recentes no log.
- Postgres: `pg_settings`, `pg_stat_activity`, `pg_stat_statements`, `pg_stat_database` (blks_hit vs blks_read)
- MySQL/MariaDB: `SHOW GLOBAL STATUS/VARIABLES`, slow log, `Aborted_connects`, buffer pool
- MongoDB: `db.serverStatus()`, `currentOp`, profiler
- Redis/Valkey: `INFO memory|stats|clients`, `evicted_keys`, `maxmemory-policy`, `SLOWLOG GET`
- SQLite: tamanho do arquivo, journal mode (WAL?), lock contention no log da app
- RabbitMQ/filas: profundidade da fila, mensagens não confirmadas, consumidores ativos
### M5 · Aplicações
Para cada app detectada, agregue os erros por tipo em vez de ler linha por linha:
```bash
<comando de log da app> --since 24h | grep -oiE 'error|fatal|exception|timeout|ECONNREFUSED|EADDRINUSE|OOM|deadlock|traceback|panic|segfault' | sort | uniq -c | sort -rn
```
Depois abra as 5–10 linhas dos tipos mais frequentes para achar a causa. Verifique também: dimensionamento de workers/pool vs. vCPU, retries sem backoff, execuções travadas, jobs sobrepostos no cron, histórico/dados sem política de expurgo (causa comum de disco e de banco crescendo sem parar).
### M6 · Rede, segurança, resiliência (sempre)
Portas expostas ao mundo que deveriam ser locais; firewall ativo (`ufw`, `firewalld`, `nftables`, `iptables`, ou o firewall do provedor); tentativas de login falhas e proteção contra força bruta; config de SSH (root login, senha, porta); validade de certificados TLS; rotação de logs configurada e funcionando; **existência e recenticidade de backup** — se não houver backup, isso é P0, independentemente de performance; atualizações de segurança pendentes.
### M7 · Componente não coberto por esta skill
Detectou algo que os módulos acima não descrevem? Não pule e não improvise: leia `<binario> --help`, a config encontrada em 0.4 e o log; identifique as três coisas que valem para qualquer serviço — **quanto de recurso ele pode usar, quantas requisições/conexões simultâneas ele aceita, e o que ele está reclamando no log** — e audite por esse eixo. Registre no relatório como componente não padrão, com a base que você usou.
---
## Fase 2 — Análise
Cada achado exige três coisas, ou não entra no relatório:
- **Evidência**: a métrica ou linha de log exata, com o comando que a produziu.
- **Mecanismo**: *por que* isso degrada este servidor. Sem "boa prática" genérica.
- **Impacto**: quem sofre — latência, 5xx, risco de queda, disco estourando em N dias.
Descarte o que você não sustentar com evidência desta execução. **Cinco achados reais valem mais que vinte genéricos.** Não recomende mais RAM se o gargalo medido é I/O ou uma query sem índice. Ferramenta ausente é "não verificado", nunca "está tudo bem".
Heurísticas de correlação (aplicáveis a qualquer stack):
| Sinal | Causa provável |
|---|---|
| load > 2× vCPU com `%wa` alto / PSI io alto | gargalo de disco, não de CPU |
| `si/so` > 0 constante | RAM insuficiente → latência; ou swappiness alto |
| OOM killer no dmesg | processo sem limite ou com leak; container sem `memory` |
| 502/503/504 no proxy | upstream lento ou pool de workers da app pequeno |
| 499 / client closed | timeout do cliente antes do backend responder |
| conexões de DB no limite | pool do app mal dimensionado (não é "aumentar max_connections") |
| `/var/log`, journal ou LogPath em GBs | rotação ausente ou log driver sem limite |
| inodes cheios com disco livre | milhares de arquivos pequenos (sessões, cache, temp) |
| RestartCount / restarts crescendo | crash loop |
| RSS de um processo crescendo entre execuções | memory leak (compare com o baseline) |
| pico periódico exato | cron/timer — correlacione o horário |
Classifique: **P0** (risco de queda ou perda de dados agora, backup inexistente), **P1** (degradação medida), **P2** (eficiência/custo), **P3** (higiene).
---
## Fase 3 — Relatório + baseline
Escreva em `./.auditoria-servidor/` (ou num diretório gravável que o usuário indicar; se estiver rodando como root em produção, `/var/log/auditoria-servidor/` serve).
`relatorio-YYYY-MM-DD.md`:
```markdown
# Auditoria — <host> — <data>
## Resumo
<3–5 linhas: estado geral, gargalo principal, risco mais urgente.>
## Stack detectada
<o perfil da Fase 0.5, incluindo se é container e quais limites reais>
## Achados
### [P0] <título>
- **Evidência:** `<comando>` → `<saída>`
- **Mecanismo:** ...
- **Impacto:** ...
- **Correção proposta:** `<comando ou diff exato>`
- **Risco / rollback:** `<backup + reversão>` · precisa restart? sim/não
## Métricas desta execução
| Métrica | Valor |
## Comparação com a execução anterior
<o que melhorou, piorou ou apareceu>
## Não verificado
<o que faltou: sem root, ferramenta ausente, log inacessível, só visão de dentro do container>
```
`baseline.json` — **acumule um array de execuções; nunca sobrescreva o histórico.** Como a stack varia, guarde métricas em chaves genéricas mais um bloco por componente detectado:
```json
{"data":"","stack":{"os":"","init":"","containerizado":false,"componentes":[]},
"recursos":{"load1":0,"vcpu":0,"mem_used_pct":0,"swap_mb":0,"disk_pct":{},"inodes_pct":{},"psi_io":0},
"processos":{"top_rss":{}},"logs":{"maiores_mb":{},"erros_24h_por_tipo":{}},
"componentes":{"<nome>":{"<metrica>":0}},
"achados":{"p0":0,"p1":0,"p2":0,"p3":0},"aplicados":[],"nao_verificado":[]}
```
Leia o baseline **antes** de coletar. Havendo execução anterior, a comparação é obrigatória — **tendência vale mais que valor absoluto** (disco subindo 2%/dia é mais grave que disco parado em 60%) — e não reproponha item já aplicado ou já recusado pelo usuário.
No chat, entregue só o resumo e uma linha por achado, agrupados por severidade. O detalhe fica no arquivo.
---
## Fase 4 — Aplicação (só com aprovação)
Pergunte quais itens aplicar. Para **cada** item aprovado, nesta ordem:
1. Mostre o diff/comando exato.
2. Backup do arquivo (`.bak.$(date +%F-%H%M)`).
3. Aplique.
4. Valide com o verificador do próprio produto (`nginx -t`, `apachectl configtest`, `caddy validate`, `haproxy -c`, `sshd -t`, `docker compose config`, `<db> --help` para checar sintaxe de parâmetro).
5. Se exigir restart, confirme de novo; prefira `reload`; **nunca reinicie o SSH sem uma segunda sessão aberta e confirmada**.
6. Meça o efeito com o mesmo comando da evidência e registre em `aplicados[]`.
7. Falhou ou piorou? **Rollback imediato** e reporte.
Mudanças de tuning de banco ou de limites de kernel vão **uma por vez**, com valor justificado pelos recursos reais medidos e com o valor anterior anotado. Ajuste que só vive em memória (`sysctl -w`, `SET GLOBAL`) precisa da versão persistente proposta junto, ou não sobrevive ao reboot — diga isso explicitamente.
Encerre com: o que foi aplicado, o que ficou pendente e por quê, e como reverter tudo.
---
## Atalho: "só dê uma olhada nos logs"
Faça 0.1–0.4 de qualquer forma (é rápido e evita analisar log no vácuo), vá aos logs relevantes e responda no chat. Relatório completo só se o usuário pedir ou se aparecer um P0.
Requisitos e permissões
Dependências
- Agente com acesso ao terminal no servidor auditado.
- Ambiente Linux; ferramentas e componentes devem ser descobertos antes do uso.
Permissões declaradas
- Leitura de processos, métricas, logs e configurações disponíveis no servidor.
- Gravação do relatório e do histórico de baseline no diretório indicado.
- Privilégios administrativos apenas quando necessários e disponíveis; limitações devem ser registradas.
- Correções e alterações no servidor somente com aprovação explícita por item, conforme as instruções.
Compatibilidade de formato: Agent Skills. A descoberta e a ativação dependem do suporte do seu agente.
Avaliações
Carregando…Histórico de versões
- v1.0.02026-09-15 · Disponível
Primeira publicação do texto fornecido pelo mantenedor, preservando as fases de descoberta, coleta, análise, relatório e aplicação aprovada.