Automatizar criação de contas no HestiaCP é etapa obrigatória quando o painel precisa operar acoplado a billing (WHMCS), ERP interno ou pipeline de onboarding. O ganho é direto: menos intervenção manual, menor tempo de entrega e trilha operacional auditável.
Neste artigo, documento exatamente como estruturei esse fluxo: validação local de comandos, chamada remota via API, troubleshooting de autenticação/conectividade e controles de segurança para produção.
1) Arquitetura real da API do HestiaCP
A API do HestiaCP atua como wrapper dos comandos CLI (v-*). Na prática, você envia um POST para o endpoint de administração e o painel executa o comando correspondente no backend.
Endpoint padrão:
https://SEU_SERVIDOR:8083/api/
Parâmetros essenciais:
user: usuário administrativo (ou usuário com permissão adequada)password: senha do usuário da APIhash: access hash/api keycmd: comando (v-add-user,v-add-domain, etc.)arg1 ... argN: argumentos na ordem esperada pelo comando CLI
Regra operacional: a API só é previsível quando você já validou o comando equivalente no shell.
2) Pré-validação obrigatória no servidor (CLI primeiro)
Antes de integrar PHP/WHMCS, valide diretamente no host se a sintaxe e permissões do comando estão corretas.
Exemplo de criação de usuário:
v-add-user novo_usuario 'SenhaForte123!' email@cliente.com default Nome Sobrenome
echo $?
Se o retorno (exit code) não for 0, não avance para API. Corrija no nível CLI primeiro.
Checklist mínimo no host:
which v-add-user
v-list-user admin json
v-list-packages json
Isso evita perder tempo depurando aplicação quando o problema está no próprio painel/pacote/permissão.
3) Teste de API isolado com cURL
Com CLI validado, repliquei o mesmo fluxo via HTTP para eliminar variáveis do sistema chamador.
curl -k -X POST "https://seu-servidor.com:8083/api/" \
-d "user=admin" \
-d "password=SUA_SENHA" \
-d "hash=SEU_HASH" \
-d "cmd=v-add-user" \
-d "arg1=novo_usuario" \
-d "arg2=SenhaForte123" \
-d "arg3=email@cliente.com" \
-d "arg4=default" \
-d "arg5=Nome" \
-d "arg6=Sobrenome"
Durante debug, usei -k apenas para isolar TLS. Em produção, o correto é certificado válido + verificação habilitada.
Diagnóstico HTTP detalhado:
curl -vk -X POST "https://seu-servidor.com:8083/api/" -d "..."
Esse passo mostrou rapidamente se a falha era autenticação, payload malformado ou bloqueio de rede.
4) Implementação robusta em PHP
No integrador PHP, padronizei envio com http_build_query() para garantir encoding correto e evitar quebra de parâmetros com caracteres especiais.
<?php
$endpoint = 'https://seu-servidor.com:8083/api/';
$payload = [
'user' => 'admin',
'password' => 'SUA_SENHA',
'hash' => 'SEU_HASH',
'cmd' => 'v-add-user',
'arg1' => 'novo_usuario',
'arg2' => 'SenhaForte123',
'arg3' => 'email@cliente.com',
'arg4' => 'default',
'arg5' => 'Nome',
'arg6' => 'Sobrenome',
];
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno) {
throw new RuntimeException("cURL error [$errno]: $error");
}
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException("HTTP error [$httpCode] response: " . ($response ?? ''));
}
if ($response === false || trim($response) === '') {
throw new RuntimeException('API response empty. Check auth/hash/firewall.');
}
echo $response;
Pontos que salvaram tempo de troubleshooting:
- log de
httpCode - log de tempo/timeout
- log de payload sem segredo (redaction de senha/hash)
- fallback de retry controlado para timeout de rede
5) Falhas recorrentes que encontrei em produção
5.1 Hash inválido ou expirado
Sintoma: resposta vazia, erro de autenticação ou execução negada.
Mitigação:
- regenerar Access Key no painel (
User -> Access Keys) - ou CLI (
v-add-api-key) - rotacionar hash com política de segredo e revogação de chave antiga
5.2 Encoding quebrando args
Sintoma: nome/email com caracteres especiais gera comando corrompido.
Mitigação:
- sempre
http_build_query() - normalização de input (trim, charset, whitelist de caracteres por campo)
5.3 Firewall bloqueando porta 8083
Sintoma: timeout, connection refused ou handshake interrompido.
Mitigação:
# validar conectividade
nc -vz seu-servidor.com 8083
# validar regra (exemplo UFW)
ufw status
# exemplo de liberação controlada
ufw allow from IP_ORIGEM to any port 8083 proto tcp
5.4 Divergência de pacote/limite
Sintoma: API responde erro de criação por pacote inexistente ou limite.
Mitigação:
v-list-packages json
v-list-user admin json
Validar se arg4 (package) existe e se o operador tem permissão para provisionar nesse perfil.
6) Segurança operacional que implementei
- Segredos fora do código (env/secret manager).
- Mascaramento de senha/hash nos logs.
- TLS válido no hostname do painel (Let's Encrypt).
CURLOPT_SSL_VERIFYPEER=trueeCURLOPT_SSL_VERIFYHOST=2em produção.- ACL de origem na porta 8083 (somente IPs do provisionador).
- Auditoria de tentativas de provisionamento com correlation id por requisição.
Exemplo de log seguro:
request_id=prov-20260302-001 cmd=v-add-user user=admin target=novo_usuario package=default http=200 result=ok
7) Runbook de validação pós-implementação
Após deploy da automação, executei sequência de aceite:
- criar usuário via API
- criar domínio vinculado ao usuário
- validar conta no painel
- validar estrutura em disco
- validar serviço web/dns/mail conforme pacote
Comandos usados no pós-check:
v-list-user novo_usuario json
v-list-web-domains novo_usuario json
v-list-dns-domains novo_usuario json
Com isso, a automação ficou observável e previsível, sem “provisionamento fantasma”.
8) Resultado técnico
Com esse modelo, passei de criação manual para fluxo API com tempo de entrega de segundos, mantendo controle de segurança e trilha de auditoria. O principal ganho não foi só velocidade, foi consistência operacional.
Resumo prático:
- valide CLI primeiro
- replique com cURL
- só depois integre no PHP/WHMCS
- trate segurança como requisito de projeto, não como pós-ajuste
Este post está licenciado sob CC BY-NC.
Comentários
Participe da discussão abaixo.
Comentários ainda não configurados. Adicione as opções do Cusdis em /assets/json/config/blog-comments-config.json.