[{"data":1,"prerenderedAt":1015},["ShallowReactive",2],{"doc-en-\u002Fen\u002Fdocs\u002Fobservability\u002Fbackup-restore":3,"docs-en-all":946},{"id":4,"title":5,"body":6,"category":930,"description":931,"draft":932,"extension":933,"icon":934,"lastReviewed":935,"meta":936,"navigation":158,"order":140,"path":937,"prerequisites":938,"readingTime":939,"seo":940,"stem":941,"tags":942,"__hash__":945},"docs_en\u002Fen\u002Fdocs\u002Fobservability\u002Fbackup-restore.md","Backup and restore of cluster state",{"type":7,"value":8,"toc":912},"minimark",[9,13,18,26,29,32,46,50,53,81,84,92,95,117,120,124,127,228,236,240,243,246,371,374,434,439,442,459,462,466,480,483,509,512,516,519,540,543,579,586,590,593,597,600,603,606,630,633,637,643,646,664,667,671,674,688,691,695,698,701,751,754,765,768,772,775,795,798,809,812,816,881,884,908],[10,11,12],"p",{},"A cluster backup is not the same thing as a backup of your data. They are two universes. This guide deals only with the first.",[14,15,17],"h2",{"id":16},"what-cluster-state-is","What cluster state is",[10,19,20,21,25],{},"HeroCtl keeps a catalog of what exists: declared jobs, stored secrets, ACL rules, recent metric history, configured ingress, known nodes. All of this is the ",[22,23,24],"strong",{},"control plane state",".",[10,27,28],{},"If you lose this state, the cluster forgets what should be running. The containers may stay up, but no one knows how to manage them anymore. It's the kind of situation that ends in a manual rebuild.",[10,30,31],{},"Backing up this state is cheap. Not doing it is expensive.",[33,34,35],"blockquote",{},[10,36,37,40,41,45],{},[22,38,39],{},"What does NOT go into the snapshot:"," the data living inside your containers. Postgres database, volumes, user uploads. Those need their own backup (",[42,43,44],"code",{},"pg_dump",", storage snapshots, etc.).",[14,47,49],{"id":48},"manual-snapshot","Manual snapshot",[10,51,52],{},"The command is one line:",[54,55,60],"pre",{"className":56,"code":57,"language":58,"meta":59,"style":59},"language-bash shiki shiki-themes github-dark-default","heroctl snapshot save \u002Ftmp\u002Fsnap-2026-04-26.tar.gz\n","bash","",[42,61,62],{"__ignoreMap":59},[63,64,67,71,75,78],"span",{"class":65,"line":66},"line",1,[63,68,70],{"class":69},"sQhOw","heroctl",[63,72,74],{"class":73},"s9uIt"," snapshot",[63,76,77],{"class":73}," save",[63,79,80],{"class":73}," \u002Ftmp\u002Fsnap-2026-04-26.tar.gz\n",[10,82,83],{},"The output:",[54,85,90],{"className":86,"code":88,"language":89},[87],"language-text","snapshot saved: 4.2 MB\nincluded: 47 jobs, 23 secrets, 12 acl rules, 4 nodes\nduration: 1.3s\n","text",[42,91,88],{"__ignoreMap":59},[10,93,94],{},"Internally the file is a compressed tarball with:",[96,97,98,102,105,108,111,114],"ul",{},[99,100,101],"li",{},"Job definitions",[99,103,104],{},"Secrets (encrypted)",[99,106,107],{},"ACL policies and tokens",[99,109,110],{},"Ingress configuration",[99,112,113],{},"List of known nodes",[99,115,116],{},"Metric history from the last 7 days",[10,118,119],{},"It does not include old logs or container images.",[14,121,123],{"id":122},"restore","Restore",[10,125,126],{},"Restoring is more delicate. The cluster needs to be stopped:",[54,128,130],{"className":56,"code":129,"language":58,"meta":59,"style":59},"# Para o cluster em todos os nós\nsudo systemctl stop heroctl-server\n\n# Em UM nó, restaura o snapshot\nheroctl snapshot restore \u002Fbackups\u002Fsnap-2026-04-26.tar.gz\n\n# Sobe o nó restaurado\nsudo systemctl start heroctl-server\n\n# Os demais nós sincronizam automaticamente ao subir\nsudo systemctl start heroctl-server  # nos outros\n",[42,131,132,138,153,160,166,179,184,190,202,207,213],{"__ignoreMap":59},[63,133,134],{"class":65,"line":66},[63,135,137],{"class":136},"sH3jZ","# Para o cluster em todos os nós\n",[63,139,141,144,147,150],{"class":65,"line":140},2,[63,142,143],{"class":69},"sudo",[63,145,146],{"class":73}," systemctl",[63,148,149],{"class":73}," stop",[63,151,152],{"class":73}," heroctl-server\n",[63,154,156],{"class":65,"line":155},3,[63,157,159],{"emptyLinePlaceholder":158},true,"\n",[63,161,163],{"class":65,"line":162},4,[63,164,165],{"class":136},"# Em UM nó, restaura o snapshot\n",[63,167,169,171,173,176],{"class":65,"line":168},5,[63,170,70],{"class":69},[63,172,74],{"class":73},[63,174,175],{"class":73}," restore",[63,177,178],{"class":73}," \u002Fbackups\u002Fsnap-2026-04-26.tar.gz\n",[63,180,182],{"class":65,"line":181},6,[63,183,159],{"emptyLinePlaceholder":158},[63,185,187],{"class":65,"line":186},7,[63,188,189],{"class":136},"# Sobe o nó restaurado\n",[63,191,193,195,197,200],{"class":65,"line":192},8,[63,194,143],{"class":69},[63,196,146],{"class":73},[63,198,199],{"class":73}," start",[63,201,152],{"class":73},[63,203,205],{"class":65,"line":204},9,[63,206,159],{"emptyLinePlaceholder":158},[63,208,210],{"class":65,"line":209},10,[63,211,212],{"class":136},"# Os demais nós sincronizam automaticamente ao subir\n",[63,214,216,218,220,222,225],{"class":65,"line":215},11,[63,217,143],{"class":69},[63,219,146],{"class":73},[63,221,199],{"class":73},[63,223,224],{"class":73}," heroctl-server",[63,226,227],{"class":136},"  # nos outros\n",[33,229,230],{},[10,231,232,235],{},[22,233,234],{},"Warning:"," restore overwrites the current state. If the snapshot is from yesterday, you lose everything that happened since then. Take a snapshot of the current state first, even if it's broken — it can preserve evidence.",[14,237,239],{"id":238},"automatic-backup-business-plan","Automatic backup (Business plan)",[10,241,242],{},"Manual snapshots work. Scheduled snapshots work more.",[10,244,245],{},"Configuration:",[54,247,251],{"className":248,"code":249,"language":250,"meta":59,"style":59},"language-yaml shiki shiki-themes github-dark-default","# \u002Fetc\u002Fheroctl\u002Fserver.yaml\nbackup:\n  enabled: true\n  schedule: \"0 3 * * *\"        # 3h da manhã, todo dia\n  retention_days: 30\n  storage:\n    type: s3\n    bucket: heroctl-backups\n    region: us-east-2\n    prefix: cluster-prod\u002F\n    access_key_id: AKIA...\n    secret_access_key: \u003Cem segredo>\n","yaml",[42,252,253,258,268,280,293,303,310,320,330,340,350,360],{"__ignoreMap":59},[63,254,255],{"class":65,"line":66},[63,256,257],{"class":136},"# \u002Fetc\u002Fheroctl\u002Fserver.yaml\n",[63,259,260,264],{"class":65,"line":140},[63,261,263],{"class":262},"sPWt5","backup",[63,265,267],{"class":266},"sZEs4",":\n",[63,269,270,273,276],{"class":65,"line":155},[63,271,272],{"class":262},"  enabled",[63,274,275],{"class":266},": ",[63,277,279],{"class":278},"sFSAA","true\n",[63,281,282,285,287,290],{"class":65,"line":162},[63,283,284],{"class":262},"  schedule",[63,286,275],{"class":266},[63,288,289],{"class":73},"\"0 3 * * *\"",[63,291,292],{"class":136},"        # 3h da manhã, todo dia\n",[63,294,295,298,300],{"class":65,"line":168},[63,296,297],{"class":262},"  retention_days",[63,299,275],{"class":266},[63,301,302],{"class":278},"30\n",[63,304,305,308],{"class":65,"line":181},[63,306,307],{"class":262},"  storage",[63,309,267],{"class":266},[63,311,312,315,317],{"class":65,"line":186},[63,313,314],{"class":262},"    type",[63,316,275],{"class":266},[63,318,319],{"class":73},"s3\n",[63,321,322,325,327],{"class":65,"line":192},[63,323,324],{"class":262},"    bucket",[63,326,275],{"class":266},[63,328,329],{"class":73},"heroctl-backups\n",[63,331,332,335,337],{"class":65,"line":204},[63,333,334],{"class":262},"    region",[63,336,275],{"class":266},[63,338,339],{"class":73},"us-east-2\n",[63,341,342,345,347],{"class":65,"line":209},[63,343,344],{"class":262},"    prefix",[63,346,275],{"class":266},[63,348,349],{"class":73},"cluster-prod\u002F\n",[63,351,352,355,357],{"class":65,"line":215},[63,353,354],{"class":262},"    access_key_id",[63,356,275],{"class":266},[63,358,359],{"class":73},"AKIA...\n",[63,361,363,366,368],{"class":65,"line":362},12,[63,364,365],{"class":262},"    secret_access_key",[63,367,275],{"class":266},[63,369,370],{"class":73},"\u003Cem segredo>\n",[10,372,373],{},"The schedule is cron-like. Examples:",[375,376,377,390],"table",{},[378,379,380],"thead",{},[381,382,383,387],"tr",{},[384,385,386],"th",{},"Expression",[384,388,389],{},"When",[391,392,393,404,414,424],"tbody",{},[381,394,395,401],{},[396,397,398],"td",{},[42,399,400],{},"0 3 * * *",[396,402,403],{},"3am every day",[381,405,406,411],{},[396,407,408],{},[42,409,410],{},"0 *\u002F6 * * *",[396,412,413],{},"Every 6 hours",[381,415,416,421],{},[396,417,418],{},[42,419,420],{},"0 3 * * 0",[396,422,423],{},"Sundays at 3am",[381,425,426,431],{},[396,427,428],{},[42,429,430],{},"30 2 1 * *",[396,432,433],{},"Day 1 of each month, 2:30am",[435,436,438],"h3",{"id":437},"compatible-storage","Compatible storage",[10,440,441],{},"Any S3-compatible storage works:",[96,443,444,447,450,453,456],{},[99,445,446],{},"AWS S3",[99,448,449],{},"Cloudflare R2",[99,451,452],{},"Backblaze B2",[99,454,455],{},"Wasabi",[99,457,458],{},"MinIO (self-hosted)",[10,460,461],{},"Your choice. R2 and B2 are usually the cheapest for long retention.",[435,463,465],{"id":464},"retention","Retention",[54,467,469],{"className":248,"code":468,"language":250,"meta":59,"style":59},"retention_days: 30\n",[42,470,471],{"__ignoreMap":59},[63,472,473,476,478],{"class":65,"line":66},[63,474,475],{"class":262},"retention_days",[63,477,275],{"class":266},[63,479,302],{"class":278},[10,481,482],{},"Snapshots older than 30 days are deleted automatically. You can use different values:",[96,484,485,491,497,503],{},[99,486,487,490],{},[42,488,489],{},"7"," — small teams, operational only",[99,492,493,496],{},[42,494,495],{},"30"," — recommended default",[99,498,499,502],{},[42,500,501],{},"90"," — audit, regulated environments",[99,504,505,508],{},[42,506,507],{},"365"," — heavy compliance",[10,510,511],{},"Each snapshot weighs between 2 MB and a few tens of MB. Even 365 copies take little space.",[14,513,515],{"id":514},"encryption","Encryption",[10,517,518],{},"Every snapshot is encrypted at rest with AES-256. The key is configured on the server:",[54,520,522],{"className":248,"code":521,"language":250,"meta":59,"style":59},"backup:\n  encryption_key_file: \u002Fetc\u002Fheroctl\u002Fbackup.key\n",[42,523,524,530],{"__ignoreMap":59},[63,525,526,528],{"class":65,"line":66},[63,527,263],{"class":262},[63,529,267],{"class":266},[63,531,532,535,537],{"class":65,"line":140},[63,533,534],{"class":262},"  encryption_key_file",[63,536,275],{"class":266},[63,538,539],{"class":73},"\u002Fetc\u002Fheroctl\u002Fbackup.key\n",[10,541,542],{},"Generate the key once:",[54,544,546],{"className":56,"code":545,"language":58,"meta":59,"style":59},"openssl rand -base64 32 > \u002Fetc\u002Fheroctl\u002Fbackup.key\nchmod 600 \u002Fetc\u002Fheroctl\u002Fbackup.key\n",[42,547,548,569],{"__ignoreMap":59},[63,549,550,553,556,559,562,566],{"class":65,"line":66},[63,551,552],{"class":69},"openssl",[63,554,555],{"class":73}," rand",[63,557,558],{"class":278}," -base64",[63,560,561],{"class":278}," 32",[63,563,565],{"class":564},"suJrU"," >",[63,567,568],{"class":73}," \u002Fetc\u002Fheroctl\u002Fbackup.key\n",[63,570,571,574,577],{"class":65,"line":140},[63,572,573],{"class":69},"chmod",[63,575,576],{"class":278}," 600",[63,578,568],{"class":73},[33,580,581],{},[10,582,583,585],{},[22,584,234],{}," without this key the snapshot becomes garbage. Keep a copy outside the cluster. In a password vault. On paper inside an envelope. Wherever makes sense — but keep it.",[14,587,589],{"id":588},"disaster-recovery","Disaster recovery",[10,591,592],{},"Three scenarios, three responses.",[435,594,596],{"id":595},"scenario-1-cluster-lost-coordination","Scenario 1: cluster lost coordination",[10,598,599],{},"More nodes went down than survived. The cluster locks up in read-only mode.",[10,601,602],{},"Normal solution: bring the downed nodes back. They re-sync and everything returns.",[10,604,605],{},"Emergency solution (last resort): forced bootstrap from the most recent snapshot.",[54,607,609],{"className":56,"code":608,"language":58,"meta":59,"style":59},"# Em um nó saudável\nheroctl snapshot restore \u002Fbackups\u002Fsnap-mais-recente.tar.gz --force-bootstrap\n",[42,610,611,616],{"__ignoreMap":59},[63,612,613],{"class":65,"line":66},[63,614,615],{"class":136},"# Em um nó saudável\n",[63,617,618,620,622,624,627],{"class":65,"line":140},[63,619,70],{"class":69},[63,621,74],{"class":73},[63,623,175],{"class":73},[63,625,626],{"class":73}," \u002Fbackups\u002Fsnap-mais-recente.tar.gz",[63,628,629],{"class":278}," --force-bootstrap\n",[10,631,632],{},"You lose changes made after the last snapshot.",[435,634,636],{"id":635},"scenario-2-cluster-storage-corrupted","Scenario 2: cluster storage corrupted",[10,638,639,640,25],{},"Disk died. Datacenter burned. Operator deleted ",[42,641,642],{},"\u002Fvar\u002Flib\u002Fheroctl",[10,644,645],{},"Same procedure:",[647,648,649,652,655,661],"ol",{},[99,650,651],{},"Provision new nodes.",[99,653,654],{},"Install HeroCtl.",[99,656,657,660],{},[42,658,659],{},"heroctl snapshot restore"," on one of them.",[99,662,663],{},"Have the others join as peers.",[10,665,666],{},"If you had an off-site snapshot, you recover in minutes. If you didn't, you recover in days (redoing everything from scratch).",[435,668,670],{"id":669},"scenario-3-application-data-lost","Scenario 3: application data lost",[10,672,673],{},"A cluster snapshot does not help you here. You need:",[96,675,676,682,685],{},[99,677,678,679,681],{},"Scheduled ",[42,680,44],{}," for Postgres",[99,683,684],{},"Volume snapshot for file storage",[99,686,687],{},"Replication for Redis (if persistent)",[10,689,690],{},"Each workload is responsible for its own data backup. HeroCtl orchestrates; it does not replace your application backup strategy.",[14,692,694],{"id":693},"restore-tests","Restore tests",[10,696,697],{},"A backup no one tested is not a backup. It's a file.",[10,699,700],{},"HeroCtl Business schedules automatic tests:",[54,702,704],{"className":248,"code":703,"language":250,"meta":59,"style":59},"backup:\n  test_restore:\n    enabled: true\n    schedule: \"0 4 1 * *\"     # dia 1 de cada mês, 4h\n    target: staging-cluster\n",[42,705,706,712,719,728,741],{"__ignoreMap":59},[63,707,708,710],{"class":65,"line":66},[63,709,263],{"class":262},[63,711,267],{"class":266},[63,713,714,717],{"class":65,"line":140},[63,715,716],{"class":262},"  test_restore",[63,718,267],{"class":266},[63,720,721,724,726],{"class":65,"line":155},[63,722,723],{"class":262},"    enabled",[63,725,275],{"class":266},[63,727,279],{"class":278},[63,729,730,733,735,738],{"class":65,"line":162},[63,731,732],{"class":262},"    schedule",[63,734,275],{"class":266},[63,736,737],{"class":73},"\"0 4 1 * *\"",[63,739,740],{"class":136},"     # dia 1 de cada mês, 4h\n",[63,742,743,746,748],{"class":65,"line":168},[63,744,745],{"class":262},"    target",[63,747,275],{"class":266},[63,749,750],{"class":73},"staging-cluster\n",[10,752,753],{},"Monthly the staging cluster wipes its state, restores the latest production snapshot, and runs a battery of checks:",[96,755,756,759,762],{},[99,757,758],{},"Did all jobs come back?",[99,760,761],{},"Do secrets decrypt correctly?",[99,763,764],{},"Is the ACL consistent?",[10,766,767],{},"If something fails, it alerts on the configured channel.",[14,769,771],{"id":770},"best-practices","Best practices",[10,773,774],{},"The traditional 3-2-1 backup rule applies here too:",[96,776,777,783,789],{},[99,778,779,782],{},[22,780,781],{},"3 copies"," of the snapshot",[99,784,785,788],{},[22,786,787],{},"2 different media"," (local disk + cloud)",[99,790,791,794],{},[22,792,793],{},"1 off-site"," (different provider from the cluster)",[10,796,797],{},"Applied:",[96,799,800,803,806],{},[99,801,802],{},"Copy 1: generated on the coordinator node.",[99,804,805],{},"Copy 2: replicated to an S3 bucket in the same region.",[99,807,808],{},"Copy 3: replicated to a bucket in another region or another provider.",[10,810,811],{},"When the entire datacenter goes down, it's copy 3 that saves you.",[14,813,815],{"id":814},"summary","Summary",[375,817,818,831],{},[378,819,820],{},[381,821,822,825,828],{},[384,823,824],{},"Action",[384,826,827],{},"Command",[384,829,830],{},"Frequency",[391,832,833,845,859,870],{},[381,834,835,837,842],{},[396,836,49],{},[396,838,839],{},[42,840,841],{},"heroctl snapshot save",[396,843,844],{},"Before big changes",[381,846,847,850,856],{},[396,848,849],{},"Scheduled snapshot",[396,851,852,853],{},"configured in ",[42,854,855],{},"server.yaml",[396,857,858],{},"Daily",[381,860,861,863,867],{},[396,862,123],{},[396,864,865],{},[42,866,659],{},[396,868,869],{},"In emergencies",[381,871,872,875,878],{},[396,873,874],{},"Restore test",[396,876,877],{},"automatic",[396,879,880],{},"Monthly",[10,882,883],{},"Next steps:",[96,885,886,894,901],{},[99,887,888,893],{},[889,890,892],"a",{"href":891},"\u002Fen\u002Fdocs\u002Fobservability\u002Fmetrics-logs","Metrics and alerts"," — know when the backup failed.",[99,895,896,900],{},[889,897,899],{"href":898},"\u002Fen\u002Fdocs\u002Fsecurity\u002Frbac","ACL"," — who can trigger a restore.",[99,902,903,907],{},[889,904,906],{"href":905},"\u002Fen\u002Fdocs\u002Ftroubleshooting\u002Fcommon-problems","Troubleshooting"," — when restore doesn't work.",[909,910,911],"style",{},"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 .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}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"title":59,"searchDepth":140,"depth":140,"links":913},[914,915,916,917,921,922,927,928,929],{"id":16,"depth":140,"text":17},{"id":48,"depth":140,"text":49},{"id":122,"depth":140,"text":123},{"id":238,"depth":140,"text":239,"children":918},[919,920],{"id":437,"depth":155,"text":438},{"id":464,"depth":155,"text":465},{"id":514,"depth":140,"text":515},{"id":588,"depth":140,"text":589,"children":923},[924,925,926],{"id":595,"depth":155,"text":596},{"id":635,"depth":155,"text":636},{"id":669,"depth":155,"text":670},{"id":693,"depth":140,"text":694},{"id":770,"depth":140,"text":771},{"id":814,"depth":140,"text":815},"observabilidade","How to save, schedule, and restore HeroCtl control plane snapshots. Disaster recovery strategy.",false,"md","i-lucide-archive","2026-04-26",{},"\u002Fen\u002Fdocs\u002Fobservability\u002Fbackup-restore",[],"7 min read",{"title":5,"description":931},"en\u002Fdocs\u002Fobservability\u002Fbackup-restore",[263,122,943,588,944],"snapshot","s3","lBHYDuYLvCsuR93r9z2uNwxzmcIC_M-GWwcYk4Z9JQQ",[947,953,959,964,970,975,976,980,986,991,996,1000,1005,1010],{"path":948,"title":949,"description":950,"category":951,"order":66,"icon":952},"\u002Fen\u002Fdocs\u002Fapi\u002Fapi-reference","REST API reference","Endpoints, JWT authentication, curl examples, and error patterns of the HeroCtl API.","api","i-lucide-code",{"path":954,"title":955,"description":956,"category":957,"order":66,"icon":958},"\u002Fen\u002Fdocs\u002Fdeploy\u002Ffirst-deploy","Deploy your first app","Bring up a Node.js application with a Postgres database in 50 lines of YAML. Includes health check, rolling deploy, and rollback.","deploy","i-lucide-rocket",{"path":960,"title":961,"description":962,"category":957,"order":140,"icon":963},"\u002Fen\u002Fdocs\u002Fdeploy\u002Frolling-canary-blue-green","Rolling, canary, blue-green, and rainbow","Four deploy strategies. When to use each, with complete examples and honest trade-offs.","i-lucide-git-branch",{"path":965,"title":966,"description":967,"category":968,"order":140,"icon":969},"\u002Fen\u002Fdocs\u002Fnetworking\u002Ffirewall","Firewall configuration","Which ports HeroCtl uses, which need to stay open, and which should never be exposed to the internet.","rede","i-lucide-shield",{"path":971,"title":972,"description":973,"category":968,"order":66,"icon":974},"\u002Fen\u002Fdocs\u002Fnetworking\u002Fingress-tls","Ingress and automatic TLS","How to expose applications on port 443 with certificates issued and renewed automatically, without operating an external router.","i-lucide-globe",{"path":937,"title":5,"description":931,"category":930,"order":140,"icon":934},{"path":891,"title":977,"description":978,"category":930,"order":66,"icon":979},"Metrics and logs","Collect metrics, logs, and traces without standing up an external observability stack. When it's worth it, and when to integrate with an outside tool.","i-lucide-activity",{"path":981,"title":982,"description":983,"category":984,"order":155,"icon":985},"\u002Fen\u002Fdocs\u002Foperations\u002Fcli-reference","Complete CLI reference","All heroctl commands with synopsis, flags, and example. Use as a desk reference.","operacoes","i-lucide-terminal",{"path":987,"title":988,"description":989,"category":984,"order":140,"icon":990},"\u002Fen\u002Fdocs\u002Foperations\u002Ffirst-cluster","Bring up a 3-node cluster","Form a cluster with 3 servers in under 10 minutes. Tolerates 1-node failure with no downtime.","i-lucide-network",{"path":992,"title":993,"description":994,"category":984,"order":66,"icon":995},"\u002Fen\u002Fdocs\u002Foperations\u002Finstallation","Installation","Install HeroCtl on any Linux server with Docker in a single command. Covers prerequisites, bootstrap, and verification.","i-lucide-download",{"path":997,"title":998,"description":999,"category":984,"order":162,"icon":974},"\u002Fen\u002Fdocs\u002Foperations\u002Fmulti-region","Multi-region (planned for Q4 2026)","What to expect from multi-region in HeroCtl, how to run across regions today, and the roadmap through 2027.",{"path":898,"title":1001,"description":1002,"category":1003,"order":140,"icon":1004},"RBAC and access control (Business+)","Role, policy, and token model to limit who can submit, read, and operate the cluster.","seguranca","i-lucide-users",{"path":1006,"title":1007,"description":1008,"category":1003,"order":66,"icon":1009},"\u002Fen\u002Fdocs\u002Fsecurity\u002Fsecrets","Secret management","How to keep passwords, tokens, and keys outside the job spec, with encryption at rest and versioned rotation.","i-lucide-key",{"path":905,"title":1011,"description":1012,"category":1013,"order":66,"icon":1014},"Troubleshooting common problems","The 12 most frequent problems in HeroCtl clusters, with symptom, diagnosis, and step-by-step fix.","troubleshooting","i-lucide-alert-triangle",1777362181791]