[{"data":1,"prerenderedAt":1475},["ShallowReactive",2],{"doc-es-\u002Fes\u002Fdocs\u002Fred\u002Ffirewall":3,"docs-es-all":1405},{"id":4,"title":5,"body":6,"category":1387,"description":1388,"draft":1389,"extension":1390,"icon":1391,"lastReviewed":1392,"meta":1393,"navigation":247,"order":209,"path":1394,"prerequisites":1395,"readingTime":1396,"seo":1397,"stem":1398,"tags":1399,"__hash__":1404},"docs_es\u002Fes\u002Fdocs\u002Fred\u002Ffirewall.md","Configuración de firewall",{"type":7,"value":8,"toc":1371},"minimark",[9,13,18,134,137,160,169,173,184,188,191,557,560,564,749,753,756,1098,1102,1105,1110,1113,1197,1200,1204,1207,1224,1228,1231,1237,1241,1244,1259,1263,1266,1291,1294,1298,1301,1333,1344,1348,1367],[10,11,12],"p",{},"Un cluster HeroCtl saludable tiene un conjunto pequeño y fijo de puertos. Este documento muestra cuáles son, qué hace cada uno y cómo configurar el firewall del sistema operativo para liberar exactamente lo necesario, ni más ni menos.",[14,15,17],"h2",{"id":16},"puertos-en-uso","Puertos en uso",[19,20,21,40],"table",{},[22,23,24],"thead",{},[25,26,27,31,34,37],"tr",{},[28,29,30],"th",{},"Puerto",[28,32,33],{},"Protocolo",[28,35,36],{},"Función",[28,38,39],{},"Quién necesita acceder",[41,42,43,58,70,83,96,109,121],"tbody",{},[25,44,45,49,52,55],{},[46,47,48],"td",{},"80",[46,50,51],{},"TCP",[46,53,54],{},"Router de ingress (HTTP)",[46,56,57],{},"Internet entera",[25,59,60,63,65,68],{},[46,61,62],{},"443",[46,64,51],{},[46,66,67],{},"Router de ingress (HTTPS)",[46,69,57],{},[25,71,72,75,77,80],{},[46,73,74],{},"8080",[46,76,51],{},[46,78,79],{},"API del plano de control",[46,81,82],{},"Operadores y CLI, vía VPN o allowlist",[25,84,85,88,90,93],{},[46,86,87],{},"8443",[46,89,51],{},[46,91,92],{},"Panel web TLS",[46,94,95],{},"Operadores, vía VPN o allowlist",[25,97,98,101,103,106],{},[46,99,100],{},"4646",[46,102,51],{},[46,104,105],{},"Coordinación interna entre nodos (consenso)",[46,107,108],{},"Solo otros nodos del cluster",[25,110,111,114,116,119],{},[46,112,113],{},"4647",[46,115,51],{},[46,117,118],{},"RPC entre coordinador y workers",[46,120,108],{},[25,122,123,126,129,132],{},[46,124,125],{},"4648",[46,127,128],{},"TCP+UDP",[46,130,131],{},"Gossip entre nodos",[46,133,108],{},[10,135,136],{},"La regla general es simple:",[138,139,140,148,154],"ul",{},[141,142,143,147],"li",{},[144,145,146],"strong",{},"80 y 443"," abren al mundo. Es el punto de entrada de tus aplicaciones.",[141,149,150,153],{},[144,151,152],{},"8080 y 8443"," nunca deberían estar abiertas a internet pública.",[141,155,156,159],{},[144,157,158],{},"4646, 4647 y 4648"," quedan restringidas a los IPs internos del cluster.",[161,162,163],"blockquote",{},[10,164,165,168],{},[144,166,167],{},"Atención:"," Exponer 8080 sin allowlist es el error de configuración más común en clusters nuevos. Cualquier persona con el token admin puede enviar jobs. Trata ese puerto como SSH.",[14,170,172],{"id":171},"topologia-recomendada","Topología recomendada",[174,175,180],"pre",{"className":176,"code":178,"language":179},[177],"language-text","                     internet\n                        │\n                  ┌─────┴─────┐\n                  │  80, 443  │   ← cualquier origen\n                  └─────┬─────┘\n                        │\n                ┌───────┴───────┐\n                │   nós do      │\n                │   cluster     │\n                └───────┬───────┘\n                        │\n                  ┌─────┴─────┐\n                  │ 4646-4648 │   ← apenas IPs internos\n                  └───────────┘\n                        │\n                  ┌─────┴─────┐\n                  │ 8080,8443 │   ← apenas VPN ou allowlist\n                  └───────────┘\n","text",[181,182,178],"code",{"__ignoreMap":183},"",[14,185,187],{"id":186},"ubuntu-y-debian-ufw","Ubuntu y Debian (ufw)",[10,189,190],{},"Configuración mínima para un nodo servidor:",[174,192,196],{"className":193,"code":194,"language":195,"meta":183,"style":183},"language-bash shiki shiki-themes github-dark-default","# regras default\nsudo ufw default deny incoming\nsudo ufw default allow outgoing\n\n# acesso administrativo (ajuste o IP de origem)\nsudo ufw allow from 203.0.113.10 to any port 22 proto tcp comment 'SSH operador'\nsudo ufw allow from 203.0.113.10 to any port 8080 proto tcp comment 'API'\nsudo ufw allow from 203.0.113.10 to any port 8443 proto tcp comment 'Painel'\n\n# tráfego público\nsudo ufw allow 80\u002Ftcp comment 'Ingress HTTP'\nsudo ufw allow 443\u002Ftcp comment 'Ingress HTTPS'\n\n# comunicação interna entre nós (substitua pelos IPs reais)\nfor ip in 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4; do\n  sudo ufw allow from $ip to any port 4646 proto tcp\n  sudo ufw allow from $ip to any port 4647 proto tcp\n  sudo ufw allow from $ip to any port 4648\ndone\n\nsudo ufw enable\nsudo ufw status numbered\n","bash",[181,197,198,207,227,242,249,255,295,326,357,362,368,385,402,407,413,445,475,501,523,529,534,544],{"__ignoreMap":183},[199,200,203],"span",{"class":201,"line":202},"line",1,[199,204,206],{"class":205},"sH3jZ","# regras default\n",[199,208,210,214,218,221,224],{"class":201,"line":209},2,[199,211,213],{"class":212},"sQhOw","sudo",[199,215,217],{"class":216},"s9uIt"," ufw",[199,219,220],{"class":216}," default",[199,222,223],{"class":216}," deny",[199,225,226],{"class":216}," incoming\n",[199,228,230,232,234,236,239],{"class":201,"line":229},3,[199,231,213],{"class":212},[199,233,217],{"class":216},[199,235,220],{"class":216},[199,237,238],{"class":216}," allow",[199,240,241],{"class":216}," outgoing\n",[199,243,245],{"class":201,"line":244},4,[199,246,248],{"emptyLinePlaceholder":247},true,"\n",[199,250,252],{"class":201,"line":251},5,[199,253,254],{"class":205},"# acesso administrativo (ajuste o IP de origem)\n",[199,256,258,260,262,264,267,271,274,277,280,283,286,289,292],{"class":201,"line":257},6,[199,259,213],{"class":212},[199,261,217],{"class":216},[199,263,238],{"class":216},[199,265,266],{"class":216}," from",[199,268,270],{"class":269},"sFSAA"," 203.0.113.10",[199,272,273],{"class":216}," to",[199,275,276],{"class":216}," any",[199,278,279],{"class":216}," port",[199,281,282],{"class":269}," 22",[199,284,285],{"class":216}," proto",[199,287,288],{"class":216}," tcp",[199,290,291],{"class":216}," comment",[199,293,294],{"class":216}," 'SSH operador'\n",[199,296,298,300,302,304,306,308,310,312,314,317,319,321,323],{"class":201,"line":297},7,[199,299,213],{"class":212},[199,301,217],{"class":216},[199,303,238],{"class":216},[199,305,266],{"class":216},[199,307,270],{"class":269},[199,309,273],{"class":216},[199,311,276],{"class":216},[199,313,279],{"class":216},[199,315,316],{"class":269}," 8080",[199,318,285],{"class":216},[199,320,288],{"class":216},[199,322,291],{"class":216},[199,324,325],{"class":216}," 'API'\n",[199,327,329,331,333,335,337,339,341,343,345,348,350,352,354],{"class":201,"line":328},8,[199,330,213],{"class":212},[199,332,217],{"class":216},[199,334,238],{"class":216},[199,336,266],{"class":216},[199,338,270],{"class":269},[199,340,273],{"class":216},[199,342,276],{"class":216},[199,344,279],{"class":216},[199,346,347],{"class":269}," 8443",[199,349,285],{"class":216},[199,351,288],{"class":216},[199,353,291],{"class":216},[199,355,356],{"class":216}," 'Painel'\n",[199,358,360],{"class":201,"line":359},9,[199,361,248],{"emptyLinePlaceholder":247},[199,363,365],{"class":201,"line":364},10,[199,366,367],{"class":205},"# tráfego público\n",[199,369,371,373,375,377,380,382],{"class":201,"line":370},11,[199,372,213],{"class":212},[199,374,217],{"class":216},[199,376,238],{"class":216},[199,378,379],{"class":216}," 80\u002Ftcp",[199,381,291],{"class":216},[199,383,384],{"class":216}," 'Ingress HTTP'\n",[199,386,388,390,392,394,397,399],{"class":201,"line":387},12,[199,389,213],{"class":212},[199,391,217],{"class":216},[199,393,238],{"class":216},[199,395,396],{"class":216}," 443\u002Ftcp",[199,398,291],{"class":216},[199,400,401],{"class":216}," 'Ingress HTTPS'\n",[199,403,405],{"class":201,"line":404},13,[199,406,248],{"emptyLinePlaceholder":247},[199,408,410],{"class":201,"line":409},14,[199,411,412],{"class":205},"# comunicação interna entre nós (substitua pelos IPs reais)\n",[199,414,416,420,424,427,430,433,436,439,442],{"class":201,"line":415},15,[199,417,419],{"class":418},"suJrU","for",[199,421,423],{"class":422},"sZEs4"," ip ",[199,425,426],{"class":418},"in",[199,428,429],{"class":216}," 10.0.0.1",[199,431,432],{"class":216}," 10.0.0.2",[199,434,435],{"class":216}," 10.0.0.3",[199,437,438],{"class":216}," 10.0.0.4",[199,440,441],{"class":422},"; ",[199,443,444],{"class":418},"do\n",[199,446,448,451,453,455,457,460,463,465,467,470,472],{"class":201,"line":447},16,[199,449,450],{"class":212},"  sudo",[199,452,217],{"class":216},[199,454,238],{"class":216},[199,456,266],{"class":216},[199,458,459],{"class":422}," $ip ",[199,461,462],{"class":216},"to",[199,464,276],{"class":216},[199,466,279],{"class":216},[199,468,469],{"class":269}," 4646",[199,471,285],{"class":216},[199,473,474],{"class":216}," tcp\n",[199,476,478,480,482,484,486,488,490,492,494,497,499],{"class":201,"line":477},17,[199,479,450],{"class":212},[199,481,217],{"class":216},[199,483,238],{"class":216},[199,485,266],{"class":216},[199,487,459],{"class":422},[199,489,462],{"class":216},[199,491,276],{"class":216},[199,493,279],{"class":216},[199,495,496],{"class":269}," 4647",[199,498,285],{"class":216},[199,500,474],{"class":216},[199,502,504,506,508,510,512,514,516,518,520],{"class":201,"line":503},18,[199,505,450],{"class":212},[199,507,217],{"class":216},[199,509,238],{"class":216},[199,511,266],{"class":216},[199,513,459],{"class":422},[199,515,462],{"class":216},[199,517,276],{"class":216},[199,519,279],{"class":216},[199,521,522],{"class":269}," 4648\n",[199,524,526],{"class":201,"line":525},19,[199,527,528],{"class":418},"done\n",[199,530,532],{"class":201,"line":531},20,[199,533,248],{"emptyLinePlaceholder":247},[199,535,537,539,541],{"class":201,"line":536},21,[199,538,213],{"class":212},[199,540,217],{"class":216},[199,542,543],{"class":216}," enable\n",[199,545,547,549,551,554],{"class":201,"line":546},22,[199,548,213],{"class":212},[199,550,217],{"class":216},[199,552,553],{"class":216}," status",[199,555,556],{"class":216}," numbered\n",[10,558,559],{},"En nodos que son solo worker (sin panel expuesto), salta las líneas 8080 y 8443.",[14,561,563],{"id":562},"rhel-fedora-almalinux-firewalld","RHEL, Fedora, AlmaLinux (firewalld)",[174,565,567],{"className":193,"code":566,"language":195,"meta":183,"style":183},"# zonas separadas: pública para 80\u002F443, interna para portas de cluster\nsudo firewall-cmd --permanent --zone=public --add-service=http\nsudo firewall-cmd --permanent --zone=public --add-service=https\n\n# zona internal recebe os IPs do cluster\nsudo firewall-cmd --permanent --zone=internal --add-source=10.0.0.0\u002F24\nsudo firewall-cmd --permanent --zone=internal --add-port=4646\u002Ftcp\nsudo firewall-cmd --permanent --zone=internal --add-port=4647\u002Ftcp\nsudo firewall-cmd --permanent --zone=internal --add-port=4648\u002Ftcp\nsudo firewall-cmd --permanent --zone=internal --add-port=4648\u002Fudp\n\n# acesso admin: zone trusted com IP do operador\nsudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10\nsudo firewall-cmd --permanent --zone=trusted --add-port=8080\u002Ftcp\nsudo firewall-cmd --permanent --zone=trusted --add-port=8443\u002Ftcp\n\nsudo firewall-cmd --reload\nsudo firewall-cmd --list-all-zones\n",[181,568,569,574,590,603,607,612,626,639,652,665,678,682,687,701,714,727,731,740],{"__ignoreMap":183},[199,570,571],{"class":201,"line":202},[199,572,573],{"class":205},"# zonas separadas: pública para 80\u002F443, interna para portas de cluster\n",[199,575,576,578,581,584,587],{"class":201,"line":209},[199,577,213],{"class":212},[199,579,580],{"class":216}," firewall-cmd",[199,582,583],{"class":269}," --permanent",[199,585,586],{"class":269}," --zone=public",[199,588,589],{"class":269}," --add-service=http\n",[199,591,592,594,596,598,600],{"class":201,"line":229},[199,593,213],{"class":212},[199,595,580],{"class":216},[199,597,583],{"class":269},[199,599,586],{"class":269},[199,601,602],{"class":269}," --add-service=https\n",[199,604,605],{"class":201,"line":244},[199,606,248],{"emptyLinePlaceholder":247},[199,608,609],{"class":201,"line":251},[199,610,611],{"class":205},"# zona internal recebe os IPs do cluster\n",[199,613,614,616,618,620,623],{"class":201,"line":257},[199,615,213],{"class":212},[199,617,580],{"class":216},[199,619,583],{"class":269},[199,621,622],{"class":269}," --zone=internal",[199,624,625],{"class":269}," --add-source=10.0.0.0\u002F24\n",[199,627,628,630,632,634,636],{"class":201,"line":297},[199,629,213],{"class":212},[199,631,580],{"class":216},[199,633,583],{"class":269},[199,635,622],{"class":269},[199,637,638],{"class":269}," --add-port=4646\u002Ftcp\n",[199,640,641,643,645,647,649],{"class":201,"line":328},[199,642,213],{"class":212},[199,644,580],{"class":216},[199,646,583],{"class":269},[199,648,622],{"class":269},[199,650,651],{"class":269}," --add-port=4647\u002Ftcp\n",[199,653,654,656,658,660,662],{"class":201,"line":359},[199,655,213],{"class":212},[199,657,580],{"class":216},[199,659,583],{"class":269},[199,661,622],{"class":269},[199,663,664],{"class":269}," --add-port=4648\u002Ftcp\n",[199,666,667,669,671,673,675],{"class":201,"line":364},[199,668,213],{"class":212},[199,670,580],{"class":216},[199,672,583],{"class":269},[199,674,622],{"class":269},[199,676,677],{"class":269}," --add-port=4648\u002Fudp\n",[199,679,680],{"class":201,"line":370},[199,681,248],{"emptyLinePlaceholder":247},[199,683,684],{"class":201,"line":387},[199,685,686],{"class":205},"# acesso admin: zone trusted com IP do operador\n",[199,688,689,691,693,695,698],{"class":201,"line":404},[199,690,213],{"class":212},[199,692,580],{"class":216},[199,694,583],{"class":269},[199,696,697],{"class":269}," --zone=trusted",[199,699,700],{"class":269}," --add-source=203.0.113.10\n",[199,702,703,705,707,709,711],{"class":201,"line":409},[199,704,213],{"class":212},[199,706,580],{"class":216},[199,708,583],{"class":269},[199,710,697],{"class":269},[199,712,713],{"class":269}," --add-port=8080\u002Ftcp\n",[199,715,716,718,720,722,724],{"class":201,"line":415},[199,717,213],{"class":212},[199,719,580],{"class":216},[199,721,583],{"class":269},[199,723,697],{"class":269},[199,725,726],{"class":269}," --add-port=8443\u002Ftcp\n",[199,728,729],{"class":201,"line":447},[199,730,248],{"emptyLinePlaceholder":247},[199,732,733,735,737],{"class":201,"line":477},[199,734,213],{"class":212},[199,736,580],{"class":216},[199,738,739],{"class":269}," --reload\n",[199,741,742,744,746],{"class":201,"line":503},[199,743,213],{"class":212},[199,745,580],{"class":216},[199,747,748],{"class":269}," --list-all-zones\n",[14,750,752],{"id":751},"iptables-directo","iptables directo",[10,754,755],{},"Si prefieres reglas explícitas, o usas un sistema sin ufw\u002Ffirewalld:",[174,757,759],{"className":193,"code":758,"language":195,"meta":183,"style":183},"# tráfego estabelecido\niptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT\niptables -A INPUT -i lo -j ACCEPT\n\n# ingress público\niptables -A INPUT -p tcp --dport 80 -j ACCEPT\niptables -A INPUT -p tcp --dport 443 -j ACCEPT\n\n# admin restrito\niptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT\niptables -A INPUT -p tcp -s 203.0.113.10 --dport 8080 -j ACCEPT\niptables -A INPUT -p tcp -s 203.0.113.10 --dport 8443 -j ACCEPT\n\n# cluster interno (repita para cada IP)\niptables -A INPUT -p tcp -s 10.0.0.0\u002F24 --dport 4646 -j ACCEPT\niptables -A INPUT -p tcp -s 10.0.0.0\u002F24 --dport 4647 -j ACCEPT\niptables -A INPUT -p tcp -s 10.0.0.0\u002F24 --dport 4648 -j ACCEPT\niptables -A INPUT -p udp -s 10.0.0.0\u002F24 --dport 4648 -j ACCEPT\n\n# default deny\niptables -P INPUT DROP\n\n# persistir\nsudo netfilter-persistent save\n",[181,760,761,766,795,813,817,822,845,866,870,875,900,924,948,952,957,982,1006,1031,1056,1060,1065,1077,1081,1087],{"__ignoreMap":183},[199,762,763],{"class":201,"line":202},[199,764,765],{"class":205},"# tráfego estabelecido\n",[199,767,768,771,774,777,780,783,786,789,792],{"class":201,"line":209},[199,769,770],{"class":212},"iptables",[199,772,773],{"class":269}," -A",[199,775,776],{"class":216}," INPUT",[199,778,779],{"class":269}," -m",[199,781,782],{"class":216}," state",[199,784,785],{"class":269}," --state",[199,787,788],{"class":216}," ESTABLISHED,RELATED",[199,790,791],{"class":269}," -j",[199,793,794],{"class":216}," ACCEPT\n",[199,796,797,799,801,803,806,809,811],{"class":201,"line":229},[199,798,770],{"class":212},[199,800,773],{"class":269},[199,802,776],{"class":216},[199,804,805],{"class":269}," -i",[199,807,808],{"class":216}," lo",[199,810,791],{"class":269},[199,812,794],{"class":216},[199,814,815],{"class":201,"line":244},[199,816,248],{"emptyLinePlaceholder":247},[199,818,819],{"class":201,"line":251},[199,820,821],{"class":205},"# ingress público\n",[199,823,824,826,828,830,833,835,838,841,843],{"class":201,"line":257},[199,825,770],{"class":212},[199,827,773],{"class":269},[199,829,776],{"class":216},[199,831,832],{"class":269}," -p",[199,834,288],{"class":216},[199,836,837],{"class":269}," --dport",[199,839,840],{"class":269}," 80",[199,842,791],{"class":269},[199,844,794],{"class":216},[199,846,847,849,851,853,855,857,859,862,864],{"class":201,"line":297},[199,848,770],{"class":212},[199,850,773],{"class":269},[199,852,776],{"class":216},[199,854,832],{"class":269},[199,856,288],{"class":216},[199,858,837],{"class":269},[199,860,861],{"class":269}," 443",[199,863,791],{"class":269},[199,865,794],{"class":216},[199,867,868],{"class":201,"line":328},[199,869,248],{"emptyLinePlaceholder":247},[199,871,872],{"class":201,"line":359},[199,873,874],{"class":205},"# admin restrito\n",[199,876,877,879,881,883,885,887,890,892,894,896,898],{"class":201,"line":364},[199,878,770],{"class":212},[199,880,773],{"class":269},[199,882,776],{"class":216},[199,884,832],{"class":269},[199,886,288],{"class":216},[199,888,889],{"class":269}," -s",[199,891,270],{"class":269},[199,893,837],{"class":269},[199,895,282],{"class":269},[199,897,791],{"class":269},[199,899,794],{"class":216},[199,901,902,904,906,908,910,912,914,916,918,920,922],{"class":201,"line":370},[199,903,770],{"class":212},[199,905,773],{"class":269},[199,907,776],{"class":216},[199,909,832],{"class":269},[199,911,288],{"class":216},[199,913,889],{"class":269},[199,915,270],{"class":269},[199,917,837],{"class":269},[199,919,316],{"class":269},[199,921,791],{"class":269},[199,923,794],{"class":216},[199,925,926,928,930,932,934,936,938,940,942,944,946],{"class":201,"line":387},[199,927,770],{"class":212},[199,929,773],{"class":269},[199,931,776],{"class":216},[199,933,832],{"class":269},[199,935,288],{"class":216},[199,937,889],{"class":269},[199,939,270],{"class":269},[199,941,837],{"class":269},[199,943,347],{"class":269},[199,945,791],{"class":269},[199,947,794],{"class":216},[199,949,950],{"class":201,"line":404},[199,951,248],{"emptyLinePlaceholder":247},[199,953,954],{"class":201,"line":409},[199,955,956],{"class":205},"# cluster interno (repita para cada IP)\n",[199,958,959,961,963,965,967,969,971,974,976,978,980],{"class":201,"line":415},[199,960,770],{"class":212},[199,962,773],{"class":269},[199,964,776],{"class":216},[199,966,832],{"class":269},[199,968,288],{"class":216},[199,970,889],{"class":269},[199,972,973],{"class":216}," 10.0.0.0\u002F24",[199,975,837],{"class":269},[199,977,469],{"class":269},[199,979,791],{"class":269},[199,981,794],{"class":216},[199,983,984,986,988,990,992,994,996,998,1000,1002,1004],{"class":201,"line":447},[199,985,770],{"class":212},[199,987,773],{"class":269},[199,989,776],{"class":216},[199,991,832],{"class":269},[199,993,288],{"class":216},[199,995,889],{"class":269},[199,997,973],{"class":216},[199,999,837],{"class":269},[199,1001,496],{"class":269},[199,1003,791],{"class":269},[199,1005,794],{"class":216},[199,1007,1008,1010,1012,1014,1016,1018,1020,1022,1024,1027,1029],{"class":201,"line":477},[199,1009,770],{"class":212},[199,1011,773],{"class":269},[199,1013,776],{"class":216},[199,1015,832],{"class":269},[199,1017,288],{"class":216},[199,1019,889],{"class":269},[199,1021,973],{"class":216},[199,1023,837],{"class":269},[199,1025,1026],{"class":269}," 4648",[199,1028,791],{"class":269},[199,1030,794],{"class":216},[199,1032,1033,1035,1037,1039,1041,1044,1046,1048,1050,1052,1054],{"class":201,"line":503},[199,1034,770],{"class":212},[199,1036,773],{"class":269},[199,1038,776],{"class":216},[199,1040,832],{"class":269},[199,1042,1043],{"class":216}," udp",[199,1045,889],{"class":269},[199,1047,973],{"class":216},[199,1049,837],{"class":269},[199,1051,1026],{"class":269},[199,1053,791],{"class":269},[199,1055,794],{"class":216},[199,1057,1058],{"class":201,"line":525},[199,1059,248],{"emptyLinePlaceholder":247},[199,1061,1062],{"class":201,"line":531},[199,1063,1064],{"class":205},"# default deny\n",[199,1066,1067,1069,1072,1074],{"class":201,"line":536},[199,1068,770],{"class":212},[199,1070,1071],{"class":269}," -P",[199,1073,776],{"class":216},[199,1075,1076],{"class":216}," DROP\n",[199,1078,1079],{"class":201,"line":546},[199,1080,248],{"emptyLinePlaceholder":247},[199,1082,1084],{"class":201,"line":1083},23,[199,1085,1086],{"class":205},"# persistir\n",[199,1088,1090,1092,1095],{"class":201,"line":1089},24,[199,1091,213],{"class":212},[199,1093,1094],{"class":216}," netfilter-persistent",[199,1096,1097],{"class":216}," save\n",[14,1099,1101],{"id":1100},"cloud-firewall-en-capa-superior","Cloud firewall en capa superior",[10,1103,1104],{},"Aun con ufw correcto en cada nodo, vale activar el firewall del proveedor de nube como segunda capa. Si el ufw cae por un cambio mal hecho, el cloud firewall sigue protegiendo.",[1106,1107,1109],"h3",{"id":1108},"digitalocean-cloud-firewall","DigitalOcean Cloud Firewall",[10,1111,1112],{},"Crea un firewall y asígnalo a todas las droplets del cluster:",[19,1114,1115,1130],{},[22,1116,1117],{},[25,1118,1119,1122,1125,1128],{},[28,1120,1121],{},"Dirección",[28,1123,1124],{},"Tipo",[28,1126,1127],{},"Origen",[28,1129,30],{},[41,1131,1132,1145,1157,1172,1185],{},[25,1133,1134,1137,1139,1142],{},[46,1135,1136],{},"Inbound",[46,1138,51],{},[46,1140,1141],{},"Anywhere",[46,1143,1144],{},"80, 443",[25,1146,1147,1149,1151,1154],{},[46,1148,1136],{},[46,1150,51],{},[46,1152,1153],{},"IPs del operador",[46,1155,1156],{},"22, 8080, 8443",[25,1158,1159,1161,1163,1169],{},[46,1160,1136],{},[46,1162,51],{},[46,1164,1165,1166],{},"Tag ",[181,1167,1168],{},"heroctl-cluster",[46,1170,1171],{},"4646, 4647, 4648",[25,1173,1174,1176,1179,1183],{},[46,1175,1136],{},[46,1177,1178],{},"UDP",[46,1180,1165,1181],{},[181,1182,1168],{},[46,1184,125],{},[25,1186,1187,1190,1193,1195],{},[46,1188,1189],{},"Outbound",[46,1191,1192],{},"All",[46,1194,1141],{},[46,1196,1192],{},[10,1198,1199],{},"Usa tags en vez de IPs para 4646-4648 — cuando agregas un nodo nuevo con la tag, ya entra en la regla.",[1106,1201,1203],{"id":1202},"aws-security-groups","AWS Security Groups",[10,1205,1206],{},"Crea dos security groups:",[138,1208,1209,1219],{},[141,1210,1211,1214,1215,1218],{},[181,1212,1213],{},"heroctl-public",": 80 y 443 desde ",[181,1216,1217],{},"0.0.0.0\u002F0",". Asígnalo a todos los nodos.",[141,1220,1221,1223],{},[181,1222,1168],{},": 4646-4648 con origen en el propio security group (self-reference). Para 8080 y 8443, source en el security group del bastion.",[1106,1225,1227],{"id":1226},"hetzner-cloud-firewall","Hetzner Cloud Firewall",[10,1229,1230],{},"Hetzner no tiene self-reference. Usa la red privada del proyecto y libera por CIDR:",[174,1232,1235],{"className":1233,"code":1234,"language":179},[177],"allow tcp 80,443 from 0.0.0.0\u002F0\nallow tcp 4646,4647,4648 from 10.0.0.0\u002F16\nallow udp 4648 from 10.0.0.0\u002F16\nallow tcp 8080,8443 from \u003Cip-do-operador>\u002F32\n",[181,1236,1234],{"__ignoreMap":183},[14,1238,1240],{"id":1239},"cloudflare-al-frente","Cloudflare al frente",[10,1242,1243],{},"Para protección contra ataques volumétricos, poner Cloudflare en modo proxy delante del cluster funciona bien. Puntos a tener en cuenta:",[138,1245,1246,1249,1256],{},[141,1247,1248],{},"Para emisión de certificado, usa DNS-01 (no HTTP-01). El modo proxy rompe HTTP-01.",[141,1250,1251,1252,1255],{},"Restringe 80 y 443 de los nodos para que acepten solo los rangos de IP de Cloudflare. La lista oficial está en ",[181,1253,1254],{},"https:\u002F\u002Fwww.cloudflare.com\u002Fips-v4",". Actualiza vía cron mensual.",[141,1257,1258],{},"Habilita \"Full (strict)\" en Cloudflare. No uses \"Flexible\" — eso hace que Cloudflare hable HTTP con tu cluster aunque el usuario tenga HTTPS.",[14,1260,1262],{"id":1261},"bloqueando-acceso-administrativo","Bloqueando acceso administrativo",[10,1264,1265],{},"La regla más importante de este documento. El puerto 8080 no puede estar accesible desde internet pública. Tres caminos viables:",[1267,1268,1269,1275,1281],"ol",{},[141,1270,1271,1274],{},[144,1272,1273],{},"VPN."," WireGuard o Tailscale entre máquinas de los operadores y el cluster. Bloquea 8080 para cualquier origen fuera de la red de la VPN. Recomendado para equipos.",[141,1276,1277,1280],{},[144,1278,1279],{},"Allowlist por IP fijo."," Funciona para operador solo con IP residencial estable o VPS bastion.",[141,1282,1283,1286,1287,1290],{},[144,1284,1285],{},"SSH tunnel."," ",[181,1288,1289],{},"ssh -L 8080:localhost:8080 servidor"," cada vez que vayas a usar la CLI. Funciona, pero genera fricción.",[10,1292,1293],{},"La combinación que más aparece en producción es VPN + cloud firewall. El operador entra en la VPN, el cloud firewall solo libera 8080 para el rango de la VPN, y el ufw del nodo hace lo mismo por dentro.",[14,1295,1297],{"id":1296},"validacion","Validación",[10,1299,1300],{},"Después de aplicar las reglas, valida desde fuera:",[174,1302,1304],{"className":193,"code":1303,"language":195,"meta":183,"style":183},"# da sua máquina, sem VPN, contra um IP do cluster\nnmap -p 80,443,8080,8443,4646,4647,4648 \u003Cip-do-no>\n",[181,1305,1306,1311],{"__ignoreMap":183},[199,1307,1308],{"class":201,"line":202},[199,1309,1310],{"class":205},"# da sua máquina, sem VPN, contra um IP do cluster\n",[199,1312,1313,1316,1318,1321,1324,1327,1330],{"class":201,"line":209},[199,1314,1315],{"class":212},"nmap",[199,1317,832],{"class":269},[199,1319,1320],{"class":216}," 80,443,8080,8443,4646,4647,4648",[199,1322,1323],{"class":418}," \u003C",[199,1325,1326],{"class":216},"ip-do-n",[199,1328,1329],{"class":422},"o",[199,1331,1332],{"class":418},">\n",[10,1334,1335,1336,1339,1340,1343],{},"Resultado correcto: 80 y 443 abiertas, todas las demás cerradas (",[181,1337,1338],{},"closed"," o ",[181,1341,1342],{},"filtered",").",[14,1345,1347],{"id":1346},"proximos-pasos","Próximos pasos",[138,1349,1350,1359],{},[141,1351,1352,1353,1358],{},"Configurar ",[1354,1355,1357],"a",{"href":1356},"\u002Fes\u002Fdocs\u002Fred\u002Fingress-tls","ingress y TLS"," para empezar a exponer aplicaciones.",[141,1360,1361,1362,1366],{},"Revisar ",[1354,1363,1365],{"href":1364},"\u002Fes\u002Fdocs\u002Fseguridad\u002Fsecretos","gestión de secretos",".",[1368,1369,1370],"style",{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}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 pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}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);}",{"title":183,"searchDepth":209,"depth":209,"links":1372},[1373,1374,1375,1376,1377,1378,1383,1384,1385,1386],{"id":16,"depth":209,"text":17},{"id":171,"depth":209,"text":172},{"id":186,"depth":209,"text":187},{"id":562,"depth":209,"text":563},{"id":751,"depth":209,"text":752},{"id":1100,"depth":209,"text":1101,"children":1379},[1380,1381,1382],{"id":1108,"depth":229,"text":1109},{"id":1202,"depth":229,"text":1203},{"id":1226,"depth":229,"text":1227},{"id":1239,"depth":209,"text":1240},{"id":1261,"depth":209,"text":1262},{"id":1296,"depth":209,"text":1297},{"id":1346,"depth":209,"text":1347},"rede","Qué puertos usa HeroCtl, cuáles necesitan estar abiertos y cuáles nunca deberían exponerse a internet.",false,"md","i-lucide-shield","2026-04-26",{},"\u002Fes\u002Fdocs\u002Fred\u002Ffirewall",[],"9 min de lectura",{"title":5,"description":1388},"es\u002Fdocs\u002Fred\u002Ffirewall",[1400,1401,770,1402,1403],"firewall","ufw","red","seguridad","Qa9x_iTnsXaVj1j4gsU4wSSJC1-ej40anb_wmZbNYSE",[1406,1412,1418,1423,1429,1434,1440,1445,1450,1455,1456,1459,1465,1469],{"path":1407,"title":1408,"description":1409,"category":1410,"order":202,"icon":1411},"\u002Fes\u002Fdocs\u002Fapi\u002Freferencia-api","Referencia de la API REST","Endpoints, autenticación JWT, ejemplos con curl y patrones de error de la API de HeroCtl.","api","i-lucide-code",{"path":1413,"title":1414,"description":1415,"category":1416,"order":202,"icon":1417},"\u002Fes\u002Fdocs\u002Fdeploy\u002Fprimer-deploy","Deploy de la primera app","Levanta una aplicación Node.js con base Postgres en 50 líneas de YAML. Incluye health check, rolling update y rollback.","deploy","i-lucide-rocket",{"path":1419,"title":1420,"description":1421,"category":1416,"order":209,"icon":1422},"\u002Fes\u002Fdocs\u002Fdeploy\u002Frolling-canary-blue-green","Rolling, canary, blue-green y rainbow","Cuatro estrategias de deploy. Cuándo usar cada una, con ejemplos completos y trade-offs honestos.","i-lucide-git-branch",{"path":1424,"title":1425,"description":1426,"category":1427,"order":209,"icon":1428},"\u002Fes\u002Fdocs\u002Fobservabilidad\u002Fbackup-restauracion","Backup y restauración del estado del cluster","Cómo guardar, programar y restaurar snapshots del plano de control de HeroCtl. Estrategia de disaster recovery.","observabilidade","i-lucide-archive",{"path":1430,"title":1431,"description":1432,"category":1427,"order":202,"icon":1433},"\u002Fes\u002Fdocs\u002Fobservabilidad\u002Fmetricas-logs","Métricas y logs","Recolección de métricas, logs y traces sin montar una pila de observabilidad externa. Cuándo vale, y cuándo integrar con herramienta de fuera.","i-lucide-activity",{"path":1435,"title":1436,"description":1437,"category":1438,"order":202,"icon":1439},"\u002Fes\u002Fdocs\u002Foperaciones\u002Finstalacion","Instalación","Instala HeroCtl en cualquier servidor Linux con Docker en un solo comando. Cubre prerrequisitos, bootstrap y verificación.","operacoes","i-lucide-download",{"path":1441,"title":1442,"description":1443,"category":1438,"order":244,"icon":1444},"\u002Fes\u002Fdocs\u002Foperaciones\u002Fmulti-region","Multi-region (en planificación Q4 2026)","Qué esperar de multi-region en HeroCtl, cómo correr en varias regiones hoy y la hoja de ruta hasta 2027.","i-lucide-globe",{"path":1446,"title":1447,"description":1448,"category":1438,"order":209,"icon":1449},"\u002Fes\u002Fdocs\u002Foperaciones\u002Fprimer-cluster","Levantar cluster de 3 nodos","Forma un cluster con 3 servidores en menos de 10 minutos. Tolera falla de 1 nodo sin indisponibilidad.","i-lucide-network",{"path":1451,"title":1452,"description":1453,"category":1438,"order":229,"icon":1454},"\u002Fes\u002Fdocs\u002Foperaciones\u002Freferencia-cli","Referencia completa del CLI","Todos los comandos heroctl con sinopsis, flags y ejemplo. Úsalo como chuleta de mesa.","i-lucide-terminal",{"path":1394,"title":5,"description":1388,"category":1387,"order":209,"icon":1391},{"path":1356,"title":1457,"description":1458,"category":1387,"order":202,"icon":1444},"Ingress y TLS automático","Cómo exponer aplicaciones por el puerto 443 con certificados emitidos y renovados automáticamente, sin operar un router externo.",{"path":1460,"title":1461,"description":1462,"category":1463,"order":209,"icon":1464},"\u002Fes\u002Fdocs\u002Fseguridad\u002Frbac","RBAC y control de acceso (Business+)","Modelo de roles, políticas y tokens para limitar quién puede enviar, leer y operar el cluster.","seguranca","i-lucide-users",{"path":1364,"title":1466,"description":1467,"category":1463,"order":202,"icon":1468},"Gestión de secretos","Cómo guardar contraseñas, tokens y claves fuera del spec del job, con cifrado en reposo y rotación versionada.","i-lucide-key",{"path":1470,"title":1471,"description":1472,"category":1473,"order":202,"icon":1474},"\u002Fes\u002Fdocs\u002Ftroubleshooting\u002Fproblemas-comunes","Troubleshooting de problemas comunes","Los 12 problemas más frecuentes en clusters HeroCtl, con síntoma, diagnóstico y corrección paso a paso.","troubleshooting","i-lucide-alert-triangle",1777362182912]