[{"data":1,"prerenderedAt":967},["ShallowReactive",2],{"doc-\u002Fdocs\u002Frede\u002Fingress-tls":3,"docs-all":898},{"id":4,"title":5,"body":6,"category":880,"description":881,"draft":882,"extension":883,"icon":884,"lastReviewed":885,"meta":886,"navigation":459,"order":35,"path":887,"prerequisites":888,"readingTime":890,"seo":891,"stem":892,"tags":893,"__hash__":897},"docs_pt\u002Fdocs\u002Frede\u002Fingress-tls.md","Ingress e TLS automático",{"type":7,"value":8,"toc":862},"minimark",[9,13,16,21,91,94,111,117,121,124,129,136,146,150,157,206,209,212,240,244,251,254,329,336,340,351,394,405,409,412,500,518,522,525,618,622,625,689,692,696,700,703,769,772,794,798,801,821,827,831,834,838,858],[10,11,12],"p",{},"O HeroCtl traz um roteador integrado embutido no plano de controle. Você não instala, não configura, não atualiza. Ao subir o cluster, o roteador já está ativo nas portas 80 e 443 de cada nó servidor.",[10,14,15],{},"Isso significa que expor uma aplicação na internet é uma linha no spec do job.",[17,18,20],"h2",{"id":19},"o-caminho-mais-curto","O caminho mais curto",[22,23,28],"pre",{"className":24,"code":25,"language":26,"meta":27,"style":27},"language-yaml shiki shiki-themes github-dark-default","job: minha-api\ningress:\n  host: api.exemplo.com\n  port: http\n  tls: true\n","yaml","",[29,30,31,48,57,68,79],"code",{"__ignoreMap":27},[32,33,36,40,44],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sPWt5","job",[32,41,43],{"class":42},"sZEs4",": ",[32,45,47],{"class":46},"s9uIt","minha-api\n",[32,49,51,54],{"class":34,"line":50},2,[32,52,53],{"class":38},"ingress",[32,55,56],{"class":42},":\n",[32,58,60,63,65],{"class":34,"line":59},3,[32,61,62],{"class":38},"  host",[32,64,43],{"class":42},[32,66,67],{"class":46},"api.exemplo.com\n",[32,69,71,74,76],{"class":34,"line":70},4,[32,72,73],{"class":38},"  port",[32,75,43],{"class":42},[32,77,78],{"class":46},"http\n",[32,80,82,85,87],{"class":34,"line":81},5,[32,83,84],{"class":38},"  tls",[32,86,43],{"class":42},[32,88,90],{"class":89},"sFSAA","true\n",[10,92,93],{},"Com isso o cluster faz três coisas em sequência:",[95,96,97,105,108],"ol",{},[98,99,100,101,104],"li",{},"Resolve o host ",[29,102,103],{},"api.exemplo.com"," para qualquer alocação saudável do job.",[98,106,107],{},"Solicita um certificado válido para esse domínio na primeira requisição.",[98,109,110],{},"Renova esse certificado antes do vencimento, sem intervenção.",[10,112,113,114,116],{},"Você só precisa apontar o DNS de ",[29,115,103],{}," para os IPs dos nós servidores. O resto roda sozinho.",[17,118,120],{"id":119},"como-o-certificado-e-emitido","Como o certificado é emitido",[10,122,123],{},"O HeroCtl usa Let's Encrypt como autoridade certificadora padrão. Por trás disso há dois mecanismos de validação suportados.",[125,126,128],"h3",{"id":127},"http-01-default","HTTP-01 (default)",[10,130,131,132,135],{},"Funciona para qualquer domínio público que aponta para o cluster. Quando uma autoridade pede prova de posse, o roteador integrado responde no caminho ",[29,133,134],{},"\u002F.well-known\u002Facme-challenge\u002F"," automaticamente. Nada precisa ser configurado.",[137,138,139],"blockquote",{},[10,140,141,145],{},[142,143,144],"strong",{},"Atenção:"," HTTP-01 exige que a porta 80 esteja acessível externamente. Se o firewall bloqueia 80, a emissão falha.",[125,147,149],{"id":148},"dns-01-para-wildcards","DNS-01 (para wildcards)",[10,151,152,153,156],{},"Se você precisa de um certificado wildcard (",[29,154,155],{},"*.exemplo.com","), use DNS-01. Configure o provedor DNS no spec do cluster:",[22,158,160],{"className":24,"code":159,"language":26,"meta":27,"style":27},"acme:\n  challenge: dns-01\n  provider: cloudflare\n  credentials:\n    api_token: ${secret.cloudflare_token}\n",[29,161,162,169,179,189,196],{"__ignoreMap":27},[32,163,164,167],{"class":34,"line":35},[32,165,166],{"class":38},"acme",[32,168,56],{"class":42},[32,170,171,174,176],{"class":34,"line":50},[32,172,173],{"class":38},"  challenge",[32,175,43],{"class":42},[32,177,178],{"class":46},"dns-01\n",[32,180,181,184,186],{"class":34,"line":59},[32,182,183],{"class":38},"  provider",[32,185,43],{"class":42},[32,187,188],{"class":46},"cloudflare\n",[32,190,191,194],{"class":34,"line":70},[32,192,193],{"class":38},"  credentials",[32,195,56],{"class":42},[32,197,198,201,203],{"class":34,"line":81},[32,199,200],{"class":38},"    api_token",[32,202,43],{"class":42},[32,204,205],{"class":46},"${secret.cloudflare_token}\n",[10,207,208],{},"Provedores suportados nativamente: Cloudflare, Route53, DigitalOcean, Hostinger, Hetzner. Outros vão por plugin externo.",[10,210,211],{},"Com DNS-01 ativo, basta declarar:",[22,213,215],{"className":24,"code":214,"language":26,"meta":27,"style":27},"ingress:\n  host: \"*.exemplo.com\"\n  tls: true\n",[29,216,217,223,232],{"__ignoreMap":27},[32,218,219,221],{"class":34,"line":35},[32,220,53],{"class":38},[32,222,56],{"class":42},[32,224,225,227,229],{"class":34,"line":50},[32,226,62],{"class":38},[32,228,43],{"class":42},[32,230,231],{"class":46},"\"*.exemplo.com\"\n",[32,233,234,236,238],{"class":34,"line":59},[32,235,84],{"class":38},[32,237,43],{"class":42},[32,239,90],{"class":89},[17,241,243],{"id":242},"redirecionamento-http-https","Redirecionamento HTTP → HTTPS",[10,245,246,247,250],{},"Quando ",[29,248,249],{},"tls: true",", todo tráfego que chega na porta 80 é redirecionado com 301 para 443. Você não precisa duplicar configuração.",[10,252,253],{},"Para forçar HSTS:",[22,255,257],{"className":24,"code":256,"language":26,"meta":27,"style":27},"ingress:\n  host: api.exemplo.com\n  tls: true\n  hsts:\n    enabled: true\n    max_age: 31536000\n    include_subdomains: true\n    preload: false\n",[29,258,259,265,273,281,288,297,308,318],{"__ignoreMap":27},[32,260,261,263],{"class":34,"line":35},[32,262,53],{"class":38},[32,264,56],{"class":42},[32,266,267,269,271],{"class":34,"line":50},[32,268,62],{"class":38},[32,270,43],{"class":42},[32,272,67],{"class":46},[32,274,275,277,279],{"class":34,"line":59},[32,276,84],{"class":38},[32,278,43],{"class":42},[32,280,90],{"class":89},[32,282,283,286],{"class":34,"line":70},[32,284,285],{"class":38},"  hsts",[32,287,56],{"class":42},[32,289,290,293,295],{"class":34,"line":81},[32,291,292],{"class":38},"    enabled",[32,294,43],{"class":42},[32,296,90],{"class":89},[32,298,300,303,305],{"class":34,"line":299},6,[32,301,302],{"class":38},"    max_age",[32,304,43],{"class":42},[32,306,307],{"class":89},"31536000\n",[32,309,311,314,316],{"class":34,"line":310},7,[32,312,313],{"class":38},"    include_subdomains",[32,315,43],{"class":42},[32,317,90],{"class":89},[32,319,321,324,326],{"class":34,"line":320},8,[32,322,323],{"class":38},"    preload",[32,325,43],{"class":42},[32,327,328],{"class":89},"false\n",[10,330,331,332,335],{},"Não habilite ",[29,333,334],{},"preload"," sem entender o compromisso. É difícil reverter.",[17,337,339],{"id":338},"multiplos-dominios-para-o-mesmo-app","Múltiplos domínios para o mesmo app",[10,341,342,343,346,347,350],{},"Padrão comum: ",[29,344,345],{},"www.exemplo.com"," e ",[29,348,349],{},"exemplo.com"," apontando para a mesma aplicação, com um sendo canônico.",[22,352,354],{"className":24,"code":353,"language":26,"meta":27,"style":27},"ingress:\n  host: exemplo.com\n  redirect_from:\n    - www.exemplo.com\n  tls: true\n",[29,355,356,362,371,378,386],{"__ignoreMap":27},[32,357,358,360],{"class":34,"line":35},[32,359,53],{"class":38},[32,361,56],{"class":42},[32,363,364,366,368],{"class":34,"line":50},[32,365,62],{"class":38},[32,367,43],{"class":42},[32,369,370],{"class":46},"exemplo.com\n",[32,372,373,376],{"class":34,"line":59},[32,374,375],{"class":38},"  redirect_from",[32,377,56],{"class":42},[32,379,380,383],{"class":34,"line":70},[32,381,382],{"class":42},"    - ",[32,384,385],{"class":46},"www.exemplo.com\n",[32,387,388,390,392],{"class":34,"line":81},[32,389,84],{"class":38},[32,391,43],{"class":42},[32,393,90],{"class":89},[10,395,396,397,400,401,404],{},"Cada domínio em ",[29,398,399],{},"redirect_from"," recebe seu próprio certificado e responde 301 para o ",[29,402,403],{},"host"," canônico.",[17,406,408],{"id":407},"roteamento-por-path","Roteamento por path",[10,410,411],{},"Mesmo host, aplicações diferentes em paths diferentes:",[22,413,415],{"className":24,"code":414,"language":26,"meta":27,"style":27},"# job: site-marketing\ningress:\n  host: exemplo.com\n  path: \u002F\n  tls: true\n\n# job: api-publica\ningress:\n  host: exemplo.com\n  path: \u002Fapi\n  tls: true\n",[29,416,417,423,429,437,447,455,461,466,472,481,491],{"__ignoreMap":27},[32,418,419],{"class":34,"line":35},[32,420,422],{"class":421},"sH3jZ","# job: site-marketing\n",[32,424,425,427],{"class":34,"line":50},[32,426,53],{"class":38},[32,428,56],{"class":42},[32,430,431,433,435],{"class":34,"line":59},[32,432,62],{"class":38},[32,434,43],{"class":42},[32,436,370],{"class":46},[32,438,439,442,444],{"class":34,"line":70},[32,440,441],{"class":38},"  path",[32,443,43],{"class":42},[32,445,446],{"class":46},"\u002F\n",[32,448,449,451,453],{"class":34,"line":81},[32,450,84],{"class":38},[32,452,43],{"class":42},[32,454,90],{"class":89},[32,456,457],{"class":34,"line":299},[32,458,460],{"emptyLinePlaceholder":459},true,"\n",[32,462,463],{"class":34,"line":310},[32,464,465],{"class":421},"# job: api-publica\n",[32,467,468,470],{"class":34,"line":320},[32,469,53],{"class":38},[32,471,56],{"class":42},[32,473,475,477,479],{"class":34,"line":474},9,[32,476,62],{"class":38},[32,478,43],{"class":42},[32,480,370],{"class":46},[32,482,484,486,488],{"class":34,"line":483},10,[32,485,441],{"class":38},[32,487,43],{"class":42},[32,489,490],{"class":46},"\u002Fapi\n",[32,492,494,496,498],{"class":34,"line":493},11,[32,495,84],{"class":38},[32,497,43],{"class":42},[32,499,90],{"class":89},[10,501,502,503,506,507,510,511,506,514,517],{},"O roteador resolve a precedência por especificidade. ",[29,504,505],{},"\u002Fapi\u002Fusers"," cai em ",[29,508,509],{},"api-publica",". ",[29,512,513],{},"\u002Fsobre",[29,515,516],{},"site-marketing",".",[17,519,521],{"id":520},"cabecalhos-customizados","Cabeçalhos customizados",[10,523,524],{},"Para adicionar ou remover headers na resposta:",[22,526,528],{"className":24,"code":527,"language":26,"meta":27,"style":27},"ingress:\n  host: api.exemplo.com\n  tls: true\n  headers:\n    add:\n      X-Frame-Options: DENY\n      X-Content-Type-Options: nosniff\n      Referrer-Policy: strict-origin\n    remove:\n      - Server\n      - X-Powered-By\n",[29,529,530,536,544,552,559,566,576,586,596,603,611],{"__ignoreMap":27},[32,531,532,534],{"class":34,"line":35},[32,533,53],{"class":38},[32,535,56],{"class":42},[32,537,538,540,542],{"class":34,"line":50},[32,539,62],{"class":38},[32,541,43],{"class":42},[32,543,67],{"class":46},[32,545,546,548,550],{"class":34,"line":59},[32,547,84],{"class":38},[32,549,43],{"class":42},[32,551,90],{"class":89},[32,553,554,557],{"class":34,"line":70},[32,555,556],{"class":38},"  headers",[32,558,56],{"class":42},[32,560,561,564],{"class":34,"line":81},[32,562,563],{"class":38},"    add",[32,565,56],{"class":42},[32,567,568,571,573],{"class":34,"line":299},[32,569,570],{"class":38},"      X-Frame-Options",[32,572,43],{"class":42},[32,574,575],{"class":46},"DENY\n",[32,577,578,581,583],{"class":34,"line":310},[32,579,580],{"class":38},"      X-Content-Type-Options",[32,582,43],{"class":42},[32,584,585],{"class":46},"nosniff\n",[32,587,588,591,593],{"class":34,"line":320},[32,589,590],{"class":38},"      Referrer-Policy",[32,592,43],{"class":42},[32,594,595],{"class":46},"strict-origin\n",[32,597,598,601],{"class":34,"line":474},[32,599,600],{"class":38},"    remove",[32,602,56],{"class":42},[32,604,605,608],{"class":34,"line":483},[32,606,607],{"class":42},"      - ",[32,609,610],{"class":46},"Server\n",[32,612,613,615],{"class":34,"line":493},[32,614,607],{"class":42},[32,616,617],{"class":46},"X-Powered-By\n",[17,619,621],{"id":620},"rate-limiting-basico","Rate limiting básico",[10,623,624],{},"Defesa em primeira linha contra abuso:",[22,626,628],{"className":24,"code":627,"language":26,"meta":27,"style":27},"ingress:\n  host: api.exemplo.com\n  tls: true\n  rate_limit:\n    requests_per_second: 100\n    burst: 200\n    by: ip\n",[29,629,630,636,644,652,659,669,679],{"__ignoreMap":27},[32,631,632,634],{"class":34,"line":35},[32,633,53],{"class":38},[32,635,56],{"class":42},[32,637,638,640,642],{"class":34,"line":50},[32,639,62],{"class":38},[32,641,43],{"class":42},[32,643,67],{"class":46},[32,645,646,648,650],{"class":34,"line":59},[32,647,84],{"class":38},[32,649,43],{"class":42},[32,651,90],{"class":89},[32,653,654,657],{"class":34,"line":70},[32,655,656],{"class":38},"  rate_limit",[32,658,56],{"class":42},[32,660,661,664,666],{"class":34,"line":81},[32,662,663],{"class":38},"    requests_per_second",[32,665,43],{"class":42},[32,667,668],{"class":89},"100\n",[32,670,671,674,676],{"class":34,"line":299},[32,672,673],{"class":38},"    burst",[32,675,43],{"class":42},[32,677,678],{"class":89},"200\n",[32,680,681,684,686],{"class":34,"line":310},[32,682,683],{"class":38},"    by",[32,685,43],{"class":42},[32,687,688],{"class":46},"ip\n",[10,690,691],{},"Limites mais elaborados (por token, por endpoint, com bypass para parceiros) ficam na aplicação.",[17,693,695],{"id":694},"troubleshooting","Troubleshooting",[125,697,699],{"id":698},"certificado-nao-foi-emitido","Certificado não foi emitido",[10,701,702],{},"Cheque três coisas, em ordem:",[704,705,706,722],"table",{},[707,708,709],"thead",{},[710,711,712,716,719],"tr",{},[713,714,715],"th",{},"Sintoma",[713,717,718],{},"Causa provável",[713,720,721],{},"O que fazer",[723,724,725,740,756],"tbody",{},[710,726,727,734,737],{},[728,729,730,733],"td",{},[29,731,732],{},"dial tcp: timeout"," no log do challenge",[728,735,736],{},"Porta 80 fechada",[728,738,739],{},"Liberar 80\u002Ftcp inbound nos nós servidores",[710,741,742,747,750],{},[728,743,744],{},[29,745,746],{},"unauthorized: Invalid response",[728,748,749],{},"DNS aponta para outro lugar",[728,751,752,755],{},[29,753,754],{},"dig +short api.exemplo.com"," deve retornar IP de nó servidor",[710,757,758,763,766],{},[728,759,760],{},[29,761,762],{},"too many failed authorizations",[728,764,765],{},"Você bateu o rate limit do Let's Encrypt",[728,767,768],{},"Aguardar 1h e revisar a config antes de tentar de novo",[10,770,771],{},"Inspecione o estado da emissão:",[22,773,777],{"className":774,"code":775,"language":776,"meta":27,"style":27},"language-bash shiki shiki-themes github-dark-default","heroctl ingress cert-status api.exemplo.com\n","bash",[29,778,779],{"__ignoreMap":27},[32,780,781,785,788,791],{"class":34,"line":35},[32,782,784],{"class":783},"sQhOw","heroctl",[32,786,787],{"class":46}," ingress",[32,789,790],{"class":46}," cert-status",[32,792,793],{"class":46}," api.exemplo.com\n",[125,795,797],{"id":796},"o-certificado-venceu-sem-renovar","O certificado venceu sem renovar",[10,799,800],{},"Renovação roda 30 dias antes do vencimento. Se passou disso, há erro acumulado:",[22,802,804],{"className":774,"code":803,"language":776,"meta":27,"style":27},"heroctl ingress cert-renew api.exemplo.com --force\n",[29,805,806],{"__ignoreMap":27},[32,807,808,810,812,815,818],{"class":34,"line":35},[32,809,784],{"class":783},[32,811,787],{"class":46},[32,813,814],{"class":46}," cert-renew",[32,816,817],{"class":46}," api.exemplo.com",[32,819,820],{"class":89}," --force\n",[10,822,823,824,826],{},"Verifique também se ",[29,825,399],{}," ainda aponta para o cluster. Domínio que foi movido para outro provedor sem ser removido do spec quebra a renovação silenciosamente.",[125,828,830],{"id":829},"acme-challenge-intermitente","ACME challenge intermitente",[10,832,833],{},"Sintoma: às vezes emite, às vezes falha. Geralmente é DNS round-robin com um IP que não responde na 80, ou um Cloudflare na frente em modo proxy. Para HTTP-01, o domínio precisa resolver direto para o cluster durante o desafio. Use DNS-01 se mantiver Cloudflare proxy ligado.",[17,835,837],{"id":836},"proximos-passos","Próximos passos",[839,840,841,850],"ul",{},[98,842,843,844,849],{},"Configurar ",[845,846,848],"a",{"href":847},"\u002Fdocs\u002Frede\u002Ffirewall","firewall"," para liberar só o necessário.",[98,851,852,853,857],{},"Entender o modelo de ",[845,854,856],{"href":855},"\u002Fdocs\u002Fseguranca\u002Fsecrets","secrets"," antes de injetar tokens DNS no spec.",[859,860,861],"style",{},"html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}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 .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}",{"title":27,"searchDepth":50,"depth":50,"links":863},[864,865,869,870,871,872,873,874,879],{"id":19,"depth":50,"text":20},{"id":119,"depth":50,"text":120,"children":866},[867,868],{"id":127,"depth":59,"text":128},{"id":148,"depth":59,"text":149},{"id":242,"depth":50,"text":243},{"id":338,"depth":50,"text":339},{"id":407,"depth":50,"text":408},{"id":520,"depth":50,"text":521},{"id":620,"depth":50,"text":621},{"id":694,"depth":50,"text":695,"children":875},[876,877,878],{"id":698,"depth":59,"text":699},{"id":796,"depth":59,"text":797},{"id":829,"depth":59,"text":830},{"id":836,"depth":50,"text":837},"rede","Como expor aplicações pela porta 443 com certificados emitidos e renovados automaticamente, sem operar um roteador externo.",false,"md","i-lucide-globe","2026-04-26",{},"\u002Fdocs\u002Frede\u002Fingress-tls",[889],"primeiro-deploy","7 min",{"title":5,"description":881},"docs\u002Frede\u002Fingress-tls",[53,894,895,166,896,880],"tls","https","lets-encrypt","YHJGEC5N6LIaMy94NAart3ef06iftmXJwXAq_xTi_aI",[899,905,911,916,922,927,933,938,942,947,951,952,958,962],{"path":900,"title":901,"description":902,"category":903,"order":35,"icon":904},"\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.","api","i-lucide-code",{"path":906,"title":907,"description":908,"category":909,"order":35,"icon":910},"\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":912,"title":913,"description":914,"category":909,"order":50,"icon":915},"\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":917,"title":918,"description":919,"category":920,"order":50,"icon":921},"\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":923,"title":924,"description":925,"category":920,"order":35,"icon":926},"\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":928,"title":929,"description":930,"category":931,"order":59,"icon":932},"\u002Fdocs\u002Foperacoes\u002Fcomandos-cli","Referência completa do CLI","Todos os comandos heroctl com sinopse, flags e exemplo. Use como cola de mesa.","operacoes","i-lucide-terminal",{"path":934,"title":935,"description":936,"category":931,"order":35,"icon":937},"\u002Fdocs\u002Foperacoes\u002Finstalacao","Instalação","Instale o HeroCtl em qualquer servidor Linux com Docker em um único comando. Cobre pré-requisitos, bootstrap e verificação.","i-lucide-download",{"path":939,"title":940,"description":941,"category":931,"order":70,"icon":884},"\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.",{"path":943,"title":944,"description":945,"category":931,"order":50,"icon":946},"\u002Fdocs\u002Foperacoes\u002Fprimeiro-cluster","Subir cluster de 3 nós","Forme um cluster com 3 servidores em menos de 10 minutos. Tolera falha de 1 nó sem indisponibilidade.","i-lucide-network",{"path":847,"title":948,"description":949,"category":880,"order":50,"icon":950},"Configuração de firewall","Quais portas o HeroCtl usa, quais precisam ficar abertas, e quais nunca deveriam ser expostas à internet.","i-lucide-shield",{"path":887,"title":5,"description":881,"category":880,"order":35,"icon":884},{"path":953,"title":954,"description":955,"category":956,"order":50,"icon":957},"\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":855,"title":959,"description":960,"category":956,"order":35,"icon":961},"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":963,"title":964,"description":965,"category":694,"order":35,"icon":966},"\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.","i-lucide-alert-triangle",1777362178631]