title: Hooks Pos-Instalacao description: Executar scripts apos cada carga processada (ex: reload Traefik) author: CCS Systems date: 2026-05-23 tags: [hooks, automacao, traefik] access: public order: 5

Hooks Pos-Instalacao

Apos cada carga processada, o agent invoca um script externo em $TATUZIM_AGENT_HOOK_DIR/post-{tipo}. Util pra reload de servicos que consomem os artefatos (Traefik, nginx, postfix, etc.).

Como funciona

Agent processa carga csr_cert "traefik-cert":
  1. Gera CSR + pede cert ao server → recebe { cert_pem, ca_pem }
  2. Escreve out/traefik-cert.crt + out/traefik-cert.key
  3. POST /v1/events entrega_instalada
  4. Se /var/lib/tatuzim-agent/hooks/post-csr-cert existe E e executavel:
     Executa: post-csr-cert "traefik-cert" "<crt_path>" "<key_path>"

Caracteristicas

  • Best-effort: hook falhando NAO trava o processamento. Erro vai pra tracing::warn!.
  • Sincrono: agent espera o hook terminar antes de processar a proxima carga.
  • Sem timeout no MVP (cuidado com hooks que travam).
  • Stdout/stderr loggados (info pra stdout, warn pra stderr).

Localizacao do hook

Default: $TATUZIM_AGENT_DATA_DIR/hooks/ (que e /var/lib/tatuzim-agent/hooks/).

Override: TATUZIM_AGENT_HOOK_DIR=/etc/tatuzim-agent/hooks no env do systemd.

Nome do arquivo:

Tipo de carga Hook esperado
csr_cert hooks/post-csr-cert
selado (futuro) hooks/post-selado
push (futuro) hooks/post-push

Argumentos passados ao hook

post-csr-cert <carga_nome> <cert_path> <key_path>

Exemplo concreto:

post-csr-cert traefik-cert /var/lib/tatuzim-agent/out/traefik-cert.crt /var/lib/tatuzim-agent/out/traefik-cert.key

Exemplo 1: Reload Traefik

sudo -u tatuzim mkdir -p /var/lib/tatuzim-agent/hooks
sudo tee /var/lib/tatuzim-agent/hooks/post-csr-cert << 'EOF'
#!/bin/bash
set -euo pipefail

CARGA_NOME="$1"
CERT_PATH="$2"
KEY_PATH="$3"

case "$CARGA_NOME" in
    traefik-*)
        echo "Reloading Traefik para $CARGA_NOME ($CERT_PATH)"
        # Copia pro local que Traefik le
        cp "$CERT_PATH" /etc/traefik/certs/$(basename "$CARGA_NOME").crt
        cp "$KEY_PATH"  /etc/traefik/certs/$(basename "$CARGA_NOME").key
        # Traefik tem auto-reload via inotify se config dinamica, mas se for static:
        systemctl reload traefik
        ;;
    *)
        echo "Carga $CARGA_NOME — sem handler especifico, skip"
        ;;
esac
EOF
sudo chown tatuzim:tatuzim /var/lib/tatuzim-agent/hooks/post-csr-cert
sudo chmod 0750 /var/lib/tatuzim-agent/hooks/post-csr-cert

Pra Traefik aceitar reload sem sudo do user tatuzim, voce precisa adicionar permissao via sudoers ou polkit. Alternativa: rodar o hook com sudo:

# /etc/sudoers.d/tatuzim-agent
tatuzim ALL=(root) NOPASSWD: /bin/systemctl reload traefik

E no hook:

sudo systemctl reload traefik

Exemplo 2: Reload nginx via docker exec

Se Traefik/nginx roda em container:

#!/bin/bash
set -euo pipefail
CARGA_NOME="$1"
CERT_PATH="$2"
KEY_PATH="$3"

# Copia pra volume mountado no container
sudo install -m 0644 -o root "$CERT_PATH" /opt/nginx/certs/$(basename "$CARGA_NOME").crt
sudo install -m 0600 -o root "$KEY_PATH" /opt/nginx/certs/$(basename "$CARGA_NOME").key

# Reload via docker exec
sudo docker exec nginx_proxy nginx -s reload

Exemplo 3: Notify Slack/webhook

#!/bin/bash
CARGA_NOME="$1"
HOSTNAME=$(hostname)
TS=$(date -Iseconds)

curl -s -X POST https://hooks.slack.com/services/XXX \
    -H 'Content-Type: application/json' \
    -d "{\"text\":\"Tatuzim: agent $HOSTNAME instalou carga $CARGA_NOME em $TS\"}" \
    >/dev/null

Exemplo 4: Multiplos handlers via dispatch

Pra organizar quando voce tem varias cargas com handlers diferentes:

# /var/lib/tatuzim-agent/hooks/post-csr-cert
#!/bin/bash
set -euo pipefail
CARGA_NOME="$1"
HANDLER_DIR="/var/lib/tatuzim-agent/hooks/handlers"
SPECIFIC="$HANDLER_DIR/post-csr-cert-$CARGA_NOME"

if [ -x "$SPECIFIC" ]; then
    exec "$SPECIFIC" "$@"
fi

# Fallback handler generico
echo "Sem handler especifico pra $CARGA_NOME"

E entao:

/var/lib/tatuzim-agent/hooks/
├── post-csr-cert          # dispatcher
└── handlers/
    ├── post-csr-cert-traefik-cert
    ├── post-csr-cert-mautic-cert
    └── post-csr-cert-nginx-cert

Validar hook

Pra testar manualmente:

sudo -u tatuzim /var/lib/tatuzim-agent/hooks/post-csr-cert \
    "teste-manual" \
    "/var/lib/tatuzim-agent/out/traefik-cert.crt" \
    "/var/lib/tatuzim-agent/out/traefik-cert.key"

Permissoes

/var/lib/tatuzim-agent/hooks/      0750  tatuzim:tatuzim
└── post-csr-cert                  0750  tatuzim:tatuzim  (executavel)

Se o hook nao for executavel, agent loga warn e pula:

WARN tatuzim_agent::hooks: hook not executable, skipping

Boas praticas

  • Idempotente: hook pode ser chamado varias vezes pra mesma carga em raros casos (restart durante processamento). Faca cp -f em vez de checks.
  • Rapido: nao bloqueie o loop do agent. Pra operacoes longas, despache em background (nohup ... &).
  • Log claro: stdout/stderr vai pros logs do systemd via journal.
  • Sem secrets em args: hooks recebem paths, nao conteudo. Se precisar do conteudo do cert, leia do arquivo.

Troubleshooting

Hook nao executou

# Verificar nos logs:
journalctl -u tatuzim-agent | grep -i hook

# Possiveis:
# - "no post-csr-cert hook, skipping"  → arquivo nao existe
# - "hook not executable, skipping"    → falta +x
# - "failed to spawn hook: ..."         → erro de exec

Hook executa mas nao reflete mudancas

Verifique permissoes do destino — o user tatuzim precisa poder escrever ou voce precisa usar sudo:

# Erro tipico: tatuzim nao consegue escrever em /etc/traefik/certs/
# Solucao: setfacl ou sudoers

Proximos passos