[{"data":1,"prerenderedAt":780},["ShallowReactive",2],{"doc-\u002Fdocs\u002Foperacoes\u002Finstalacao":3,"docs-all":711},{"id":4,"title":5,"body":6,"category":694,"description":695,"draft":696,"extension":697,"icon":698,"lastReviewed":699,"meta":700,"navigation":241,"order":145,"path":701,"prerequisites":702,"readingTime":703,"seo":704,"stem":705,"tags":706,"__hash__":710},"docs_pt\u002Fdocs\u002Foperacoes\u002Finstalacao.md","Instalação",{"type":7,"value":8,"toc":680},"minimark",[9,13,18,21,110,125,129,132,165,168,207,210,214,217,275,289,323,327,330,386,389,393,396,420,431,434,468,476,480,485,491,529,535,539,556,560,563,567,581,585,588,659,670,676],[10,11,12],"p",{},"O HeroCtl roda em qualquer servidor Linux com Docker. O binário é único e contém os três modos de execução: servidor, agente e CLI. Você decide o papel da máquina via flag, não via pacote.",[14,15,17],"h2",{"id":16},"pre-requisitos","Pré-requisitos",[10,19,20],{},"Antes de instalar, confirme o ambiente. A lista é curta e firme.",[22,23,24,40],"table",{},[25,26,27],"thead",{},[28,29,30,34,37],"tr",{},[31,32,33],"th",{},"Requisito",[31,35,36],{},"Mínimo",[31,38,39],{},"Recomendado",[41,42,43,55,66,77,88,99],"tbody",{},[28,44,45,49,52],{},[46,47,48],"td",{},"Sistema",[46,50,51],{},"Linux x86_64 (kernel 5.4+)",[46,53,54],{},"Ubuntu 22.04 ou Debian 12",[28,56,57,60,63],{},[46,58,59],{},"CPU",[46,61,62],{},"2 vCPU",[46,64,65],{},"4 vCPU",[28,67,68,71,74],{},[46,69,70],{},"RAM",[46,72,73],{},"2 GB",[46,75,76],{},"4 GB",[28,78,79,82,85],{},[46,80,81],{},"Disco",[46,83,84],{},"20 GB SSD",[46,86,87],{},"40 GB SSD",[28,89,90,93,96],{},[46,91,92],{},"Docker",[46,94,95],{},"20.10+",[46,97,98],{},"24+",[28,100,101,104,107],{},[46,102,103],{},"Portas",[46,105,106],{},"8080, 8081, 8082 abertas entre nós",[46,108,109],{},"mesmo",[111,112,113],"blockquote",{},[10,114,115,119,120,124],{},[116,117,118],"strong",{},"Nota:"," o Docker precisa estar em execução antes do install. Verifique com ",[121,122,123],"code",{},"docker info",". Se a saída der erro de socket, ajuste permissões antes de prosseguir.",[14,126,128],{"id":127},"comando-de-instalacao","Comando de instalação",[10,130,131],{},"Um comando entrega o binário, configura o serviço e gera o arquivo de configuração padrão.",[133,134,139],"pre",{"className":135,"code":136,"language":137,"meta":138,"style":138},"language-bash shiki shiki-themes github-dark-default","curl -sSL https:\u002F\u002Fget.heroctl.com\u002Finstall.sh | sh\n","bash","",[121,140,141],{"__ignoreMap":138},[142,143,146,150,154,158,162],"span",{"class":144,"line":145},"line",1,[142,147,149],{"class":148},"sQhOw","curl",[142,151,153],{"class":152},"sFSAA"," -sSL",[142,155,157],{"class":156},"s9uIt"," https:\u002F\u002Fget.heroctl.com\u002Finstall.sh",[142,159,161],{"class":160},"suJrU"," |",[142,163,164],{"class":148}," sh\n",[10,166,167],{},"O script executa quatro passos, em ordem:",[169,170,171,179,193,200],"ol",{},[172,173,174,175,178],"li",{},"Baixa o binário mais recente para ",[121,176,177],{},"\u002Fusr\u002Flocal\u002Fbin\u002Fheroctl",".",[172,180,181,182,185,186,189,190,178],{},"Cria o usuário de sistema ",[121,183,184],{},"heroctl"," e os diretórios ",[121,187,188],{},"\u002Fetc\u002Fheroctl\u002F"," e ",[121,191,192],{},"\u002Fvar\u002Flib\u002Fheroctl\u002F",[172,194,195,196,199],{},"Registra um serviço systemd (",[121,197,198],{},"heroctl.service",") sem habilitar o start automático.",[172,201,202,203,206],{},"Gera ",[121,204,205],{},"\u002Fetc\u002Fheroctl\u002Fserver.yaml"," com defaults seguros (bind em 127.0.0.1, sem TLS).",[10,208,209],{},"Sem surpresas. O script não toca em nada fora desses caminhos e não inicia processos.",[14,211,213],{"id":212},"verificacao-pos-instalacao","Verificação pós-instalação",[10,215,216],{},"Após o script terminar, dois comandos confirmam que o binário responde.",[133,218,220],{"className":135,"code":219,"language":137,"meta":138,"style":138},"heroctl version\n# heroctl 1.0.0 (commit abc123, build 2026-04-20)\n\nheroctl status\n# binary: ok\n# config: \u002Fetc\u002Fheroctl\u002Fserver.yaml\n# docker: connected (24.0.7)\n# service: inactive (não iniciado)\n",[121,221,222,229,236,243,251,257,263,269],{"__ignoreMap":138},[142,223,224,226],{"class":144,"line":145},[142,225,184],{"class":148},[142,227,228],{"class":156}," version\n",[142,230,232],{"class":144,"line":231},2,[142,233,235],{"class":234},"sH3jZ","# heroctl 1.0.0 (commit abc123, build 2026-04-20)\n",[142,237,239],{"class":144,"line":238},3,[142,240,242],{"emptyLinePlaceholder":241},true,"\n",[142,244,246,248],{"class":144,"line":245},4,[142,247,184],{"class":148},[142,249,250],{"class":156}," status\n",[142,252,254],{"class":144,"line":253},5,[142,255,256],{"class":234},"# binary: ok\n",[142,258,260],{"class":144,"line":259},6,[142,261,262],{"class":234},"# config: \u002Fetc\u002Fheroctl\u002Fserver.yaml\n",[142,264,266],{"class":144,"line":265},7,[142,267,268],{"class":234},"# docker: connected (24.0.7)\n",[142,270,272],{"class":144,"line":271},8,[142,273,274],{"class":234},"# service: inactive (não iniciado)\n",[10,276,277,278,281,282,284,285,288],{},"Se ",[121,279,280],{},"docker: connected"," aparecer com erro, o binário não consegue falar com o socket. Adicione o usuário ",[121,283,184],{}," ao grupo ",[121,286,287],{},"docker"," e reinicie o serviço.",[133,290,292],{"className":135,"code":291,"language":137,"meta":138,"style":138},"sudo usermod -aG docker heroctl\nsudo systemctl restart heroctl\n",[121,293,294,311],{"__ignoreMap":138},[142,295,296,299,302,305,308],{"class":144,"line":145},[142,297,298],{"class":148},"sudo",[142,300,301],{"class":156}," usermod",[142,303,304],{"class":152}," -aG",[142,306,307],{"class":156}," docker",[142,309,310],{"class":156}," heroctl\n",[142,312,313,315,318,321],{"class":144,"line":231},[142,314,298],{"class":148},[142,316,317],{"class":156}," systemctl",[142,319,320],{"class":156}," restart",[142,322,310],{"class":156},[14,324,326],{"id":325},"os-tres-modos-do-binario","Os três modos do binário",[10,328,329],{},"O mesmo executável muda de papel pela flag inicial. Não existe pacote separado.",[22,331,332,345],{},[25,333,334],{},[28,335,336,339,342],{},[31,337,338],{},"Modo",[31,340,341],{},"Comando",[31,343,344],{},"Para quê",[41,346,347,360,373],{},[28,348,349,352,357],{},[46,350,351],{},"Servidor",[46,353,354],{},[121,355,356],{},"heroctl server",[46,358,359],{},"Plano de controle. Decide onde tudo roda.",[28,361,362,365,370],{},[46,363,364],{},"Agente",[46,366,367],{},[121,368,369],{},"heroctl agent",[46,371,372],{},"Worker. Executa contêineres e reporta saúde.",[28,374,375,378,383],{},[46,376,377],{},"CLI",[46,379,380],{},[121,381,382],{},"heroctl \u003Ccmd>",[46,384,385],{},"Cliente local. Fala com qualquer servidor via API.",[10,387,388],{},"Em produção, 3 nós rodam servidor + agente. Workers extras rodam só agente. O modo CLI é stateless e pode rodar do laptop do operador.",[14,390,392],{"id":391},"bootstrap-inicial","Bootstrap inicial",[10,394,395],{},"O primeiro nó precisa inicializar o estado do cluster. Esse passo é único e só acontece uma vez na vida da instalação.",[133,397,399],{"className":135,"code":398,"language":137,"meta":138,"style":138},"sudo heroctl server --bootstrap --advertise 10.0.0.1\n",[121,400,401],{"__ignoreMap":138},[142,402,403,405,408,411,414,417],{"class":144,"line":145},[142,404,298],{"class":148},[142,406,407],{"class":156}," heroctl",[142,409,410],{"class":156}," server",[142,412,413],{"class":152}," --bootstrap",[142,415,416],{"class":152}," --advertise",[142,418,419],{"class":152}," 10.0.0.1\n",[10,421,422,423,426,427,430],{},"A flag ",[121,424,425],{},"--advertise"," é o IP que outros nós vão usar para conectar. Em ambiente de teste, pode ser ",[121,428,429],{},"127.0.0.1",". Em produção, é o IP privado da máquina.",[10,432,433],{},"Após o bootstrap, o serviço fica em execução em segundo plano. Confirme com:",[133,435,437],{"className":135,"code":436,"language":137,"meta":138,"style":138},"heroctl cluster status\n# nodes:    1\n# leader:   self\n# applied:  42\n# health:   ok\n",[121,438,439,448,453,458,463],{"__ignoreMap":138},[142,440,441,443,446],{"class":144,"line":145},[142,442,184],{"class":148},[142,444,445],{"class":156}," cluster",[142,447,250],{"class":156},[142,449,450],{"class":144,"line":231},[142,451,452],{"class":234},"# nodes:    1\n",[142,454,455],{"class":144,"line":238},[142,456,457],{"class":234},"# leader:   self\n",[142,459,460],{"class":144,"line":245},[142,461,462],{"class":234},"# applied:  42\n",[142,464,465],{"class":144,"line":253},[142,466,467],{"class":234},"# health:   ok\n",[10,469,470,471,178],{},"Para subir nós adicionais e formar um cluster real, siga para ",[472,473,475],"a",{"href":474},"\u002Fdocs\u002Foperacoes\u002Fprimeiro-cluster","Subir cluster de 3 nós",[14,477,479],{"id":478},"problemas-comuns","Problemas comuns",[481,482,484],"h3",{"id":483},"porta-8080-em-uso","Porta 8080 em uso",[10,486,487,488,490],{},"O HeroCtl reserva 8080 para a API HTTP. Se outro processo já ocupa, edite ",[121,489,205],{}," antes do bootstrap.",[133,492,496],{"className":493,"code":494,"language":495,"meta":138,"style":138},"language-yaml shiki shiki-themes github-dark-default","api:\n  bind: 0.0.0.0\n  port: 9080\n","yaml",[121,497,498,508,519],{"__ignoreMap":138},[142,499,500,504],{"class":144,"line":145},[142,501,503],{"class":502},"sPWt5","api",[142,505,507],{"class":506},"sZEs4",":\n",[142,509,510,513,516],{"class":144,"line":231},[142,511,512],{"class":502},"  bind",[142,514,515],{"class":506},": ",[142,517,518],{"class":152},"0.0.0.0\n",[142,520,521,524,526],{"class":144,"line":238},[142,522,523],{"class":502},"  port",[142,525,515],{"class":506},[142,527,528],{"class":152},"9080\n",[10,530,531,532,178],{},"Reinicie o serviço com ",[121,533,534],{},"sudo systemctl restart heroctl",[481,536,538],{"id":537},"permissao-negada-no-docker","Permissão negada no Docker",[10,540,541,542,545,546,548,549,551,552,555],{},"A mensagem ",[121,543,544],{},"permission denied while trying to connect to the Docker daemon"," aparece quando o usuário ",[121,547,184],{}," não está no grupo ",[121,550,287],{},". Resolva com o ",[121,553,554],{},"usermod"," mostrado acima e reinicie o serviço.",[481,557,559],{"id":558},"firewall-bloqueando-o-cluster","Firewall bloqueando o cluster",[10,561,562],{},"Em provedores como DigitalOcean ou Hetzner, o firewall externo bloqueia 8080–8082 por padrão. Libere as três portas entre os IPs dos nós antes de tentar formar cluster. Para acesso externo à API, mantenha 8080 aberto apenas para IPs administrativos.",[481,564,566],{"id":565},"binario-nao-encontrado-apos-install","Binário não encontrado após install",[10,568,569,570,573,574,577,578,178],{},"O script instala em ",[121,571,572],{},"\u002Fusr\u002Flocal\u002Fbin\u002F",". Se o ",[121,575,576],{},"PATH"," da sessão atual não inclui esse diretório, abra um novo shell ou rode ",[121,579,580],{},"hash -r",[14,582,584],{"id":583},"desinstalacao","Desinstalação",[10,586,587],{},"Reverter é simétrico. Remove serviço, binário e dados, nessa ordem.",[133,589,591],{"className":135,"code":590,"language":137,"meta":138,"style":138},"sudo systemctl stop heroctl && sudo systemctl disable heroctl\nsudo rm \u002Fetc\u002Fsystemd\u002Fsystem\u002Fheroctl.service\nsudo rm \u002Fusr\u002Flocal\u002Fbin\u002Fheroctl\nsudo rm -rf \u002Fetc\u002Fheroctl \u002Fvar\u002Flib\u002Fheroctl\nsudo userdel heroctl\n",[121,592,593,616,626,635,650],{"__ignoreMap":138},[142,594,595,597,599,602,604,607,609,611,614],{"class":144,"line":145},[142,596,298],{"class":148},[142,598,317],{"class":156},[142,600,601],{"class":156}," stop",[142,603,407],{"class":156},[142,605,606],{"class":506}," && ",[142,608,298],{"class":148},[142,610,317],{"class":156},[142,612,613],{"class":156}," disable",[142,615,310],{"class":156},[142,617,618,620,623],{"class":144,"line":231},[142,619,298],{"class":148},[142,621,622],{"class":156}," rm",[142,624,625],{"class":156}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fheroctl.service\n",[142,627,628,630,632],{"class":144,"line":238},[142,629,298],{"class":148},[142,631,622],{"class":156},[142,633,634],{"class":156}," \u002Fusr\u002Flocal\u002Fbin\u002Fheroctl\n",[142,636,637,639,641,644,647],{"class":144,"line":245},[142,638,298],{"class":148},[142,640,622],{"class":156},[142,642,643],{"class":152}," -rf",[142,645,646],{"class":156}," \u002Fetc\u002Fheroctl",[142,648,649],{"class":156}," \u002Fvar\u002Flib\u002Fheroctl\n",[142,651,652,654,657],{"class":144,"line":253},[142,653,298],{"class":148},[142,655,656],{"class":156}," userdel",[142,658,310],{"class":156},[111,660,661],{},[10,662,663,666,667,669],{},[116,664,665],{},"Atenção:"," o diretório ",[121,668,192],{}," contém o estado do cluster. Apagar significa perder o histórico de deploys e definições de jobs. Faça snapshot antes se houver chance de reinstalar.",[10,671,672,673,178],{},"Próximo passo: ",[472,674,675],{"href":474},"formar um cluster de 3 nós",[677,678,679],"style",{},"html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}",{"title":138,"searchDepth":231,"depth":231,"links":681},[682,683,684,685,686,687,693],{"id":16,"depth":231,"text":17},{"id":127,"depth":231,"text":128},{"id":212,"depth":231,"text":213},{"id":325,"depth":231,"text":326},{"id":391,"depth":231,"text":392},{"id":478,"depth":231,"text":479,"children":688},[689,690,691,692],{"id":483,"depth":238,"text":484},{"id":537,"depth":238,"text":538},{"id":558,"depth":238,"text":559},{"id":565,"depth":238,"text":566},{"id":583,"depth":231,"text":584},"operacoes","Instale o HeroCtl em qualquer servidor Linux com Docker em um único comando. Cobre pré-requisitos, bootstrap e verificação.",false,"md","i-lucide-download","2026-04-26",{},"\u002Fdocs\u002Foperacoes\u002Finstalacao",[],"6 min",{"title":5,"description":695},"docs\u002Foperacoes\u002Finstalacao",[707,708,709],"instalacao","primeiros-passos","linux","tkL2axmfaGZZvBUVohKwwp1dKt6knaLHR45qdSycdOw",[712,717,723,728,734,739,744,745,750,753,759,763,769,774],{"path":713,"title":714,"description":715,"category":503,"order":145,"icon":716},"\u002Fdocs\u002Fapi\u002Freferencia-api","Referência da API REST","Endpoints, autenticação JWT, exemplos com curl e padrões de erro da API do HeroCtl.","i-lucide-code",{"path":718,"title":719,"description":720,"category":721,"order":145,"icon":722},"\u002Fdocs\u002Fdeploy\u002Fprimeiro-deploy","Deploy do primeiro app","Suba uma aplicação Node.js com banco Postgres em 50 linhas de YAML. Inclui health check, rolling deploy e rollback.","deploy","i-lucide-rocket",{"path":724,"title":725,"description":726,"category":721,"order":231,"icon":727},"\u002Fdocs\u002Fdeploy\u002Frolling-canary-bluegreen","Rolling, canary, blue-green e rainbow","Quatro estratégias de deploy. Quando usar cada uma, com exemplos completos e trade-offs honestos.","i-lucide-git-branch",{"path":729,"title":730,"description":731,"category":732,"order":231,"icon":733},"\u002Fdocs\u002Fobservabilidade\u002Fbackup-restore","Backup e restore do estado do cluster","Como salvar, agendar e restaurar snapshots do plano de controle do HeroCtl. Estratégia de disaster recovery.","observabilidade","i-lucide-archive",{"path":735,"title":736,"description":737,"category":732,"order":145,"icon":738},"\u002Fdocs\u002Fobservabilidade\u002Fmetricas-logs","Métricas e logs","Coleta de métricas, logs e traces sem montar uma pilha de observabilidade externa. Quando vale, e quando integrar com ferramenta de fora.","i-lucide-activity",{"path":740,"title":741,"description":742,"category":694,"order":238,"icon":743},"\u002Fdocs\u002Foperacoes\u002Fcomandos-cli","Referência completa do CLI","Todos os comandos heroctl com sinopse, flags e exemplo. Use como cola de mesa.","i-lucide-terminal",{"path":701,"title":5,"description":695,"category":694,"order":145,"icon":698},{"path":746,"title":747,"description":748,"category":694,"order":245,"icon":749},"\u002Fdocs\u002Foperacoes\u002Fmulti-region","Multi-region (em planejamento Q4 2026)","O que esperar de multi-region no HeroCtl, como rodar em várias regiões hoje e o roadmap até 2027.","i-lucide-globe",{"path":474,"title":475,"description":751,"category":694,"order":231,"icon":752},"Forme um cluster com 3 servidores em menos de 10 minutos. Tolera falha de 1 nó sem indisponibilidade.","i-lucide-network",{"path":754,"title":755,"description":756,"category":757,"order":231,"icon":758},"\u002Fdocs\u002Frede\u002Ffirewall","Configuração de firewall","Quais portas o HeroCtl usa, quais precisam ficar abertas, e quais nunca deveriam ser expostas à internet.","rede","i-lucide-shield",{"path":760,"title":761,"description":762,"category":757,"order":145,"icon":749},"\u002Fdocs\u002Frede\u002Fingress-tls","Ingress e TLS automático","Como expor aplicações pela porta 443 com certificados emitidos e renovados automaticamente, sem operar um roteador externo.",{"path":764,"title":765,"description":766,"category":767,"order":231,"icon":768},"\u002Fdocs\u002Fseguranca\u002Frbac","RBAC e controle de acesso (Business+)","Modelo de papéis, políticas e tokens para limitar quem pode submeter, ler e operar o cluster.","seguranca","i-lucide-users",{"path":770,"title":771,"description":772,"category":767,"order":145,"icon":773},"\u002Fdocs\u002Fseguranca\u002Fsecrets","Gerenciamento de segredos","Como guardar senhas, tokens e chaves fora do spec do job, com criptografia em repouso e rotação versionada.","i-lucide-key",{"path":775,"title":776,"description":777,"category":778,"order":145,"icon":779},"\u002Fdocs\u002Ftroubleshooting\u002Fproblemas-comuns","Troubleshooting de problemas comuns","Os 12 problemas mais frequentes em clusters HeroCtl, com sintoma, diagnóstico e correção passo a passo.","troubleshooting","i-lucide-alert-triangle",1777362178304]