[{"data":1,"prerenderedAt":1988},["ShallowReactive",2],{"article-\u002Finfraestrutura\u002Fterraform-infraestrutura-como-codigo":3},{"id":4,"title":5,"author":6,"body":7,"category":1973,"date":1974,"description":1975,"extension":1976,"keywords":1977,"meta":1982,"navigation":619,"path":1983,"seo":1984,"slug":1985,"stem":1986,"updated":1974,"__hash__":1987},"content\u002Finfraestrutura\u002Fterraform-infraestrutura-como-codigo.md","Terraform: infraestrutura como código do zero","Inicialize Tec",{"type":8,"value":9,"toc":1930},"minimark",[10,15,68,72,76,91,107,114,119,124,184,190,194,197,278,283,317,321,326,368,374,451,454,458,461,465,472,476,483,487,498,501,512,515,519,522,544,558,562,569,573,598,605,778,782,795,798,802,814,817,825,840,844,856,863,867,879,888,892,899,991,1062,1065,1093,1100,1125,1129,1136,1140,1163,1167,1178,1181,1237,1254,1258,1264,1268,1278,1283,1287,1293,1456,1553,1559,1586,1590,1596,1672,1680,1684,1691,1697,1711,1715,1731,1748,1752,1764,1769,1812,1819,1827,1832,1850,1853,1883,1887,1892,1900,1906,1913,1916,1926],[11,12,14],"h2",{"id":13},"índice","Índice",[16,17,18,26,32,38,44,50,56,62],"ol",{},[19,20,21],"li",{},[22,23,25],"a",{"href":24},"#o-que-e","O que é infraestrutura como código",[19,27,28],{},[22,29,31],{"href":30},"#por-que-terraform","Por que Terraform",[19,33,34],{},[22,35,37],{"href":36},"#conceitos","Conceitos essenciais",[19,39,40],{},[22,41,43],{"href":42},"#primeira-infra","Sua primeira infraestrutura com Terraform",[19,45,46],{},[22,47,49],{"href":48},"#variaveis","Variáveis: reutilização e flexibilidade",[19,51,52],{},[22,53,55],{"href":54},"#state","State: a memória do Terraform",[19,57,58],{},[22,59,61],{"href":60},"#modulos","Módulos: organização em larga escala",[19,63,64],{},[22,65,67],{"href":66},"#erros-comuns","Erros comuns",[11,69,71],{"id":70},"o-que-é-infraestrutura-como-código-o-que-e","O que é infraestrutura como código {#o-que-e}",[73,74,75],"p",{},"Imagine que você precisa construir uma casa. Você tem duas opções:",[16,77,78,85],{},[19,79,80,84],{},[81,82,83],"strong",{},"Ir comprando materiais no depósito e montando no sentindo",", sem planta.\nCada pedreiro faz do seu jeito. Se a casa cair, ninguém lembra exatamente\ncomo construiu.",[19,86,87,90],{},[81,88,89],{},"Contratar um arquiteto que desenha a planta completa",", com cada medida,\ncada material, cada etapa. A construtora segue a planta. Se algo cair, você\nsabe exatamente o que refazer — é só seguir a planta de novo.",[73,92,93,94,97,98,102,103,106],{},"A opção 2 é obviamente melhor. E é exatamente isso que ",[81,95,96],{},"Infraestrutura como\nCódigo"," (em inglês, ",[99,100,101],"em",{},"Infrastructure as Code",", ou ",[81,104,105],{},"IaC",") faz para seus\nservidores na nuvem.",[73,108,109,110,113],{},"Em vez de abrir o painel da AWS, clicar em \"criar servidor\", escolher\nconfigurações, clicar em \"criar banco de dados\", preencher mais formulários —\ntudo manualmente, sem rastro —, você escreve um ",[81,111,112],{},"arquivo de texto"," que\ndescreve toda a infraestrutura. Um software lê esse arquivo e cria tudo\nautomaticamente.",[73,115,116],{},[81,117,118],{},"Infraestrutura como Código é a prática de gerenciar sua infraestrutura de\nTI (servidores, bancos de dados, redes, firewalls) através de arquivos de\ntexto versionáveis, ao invés de configurações manuais em painéis.",[120,121,123],"h3",{"id":122},"os-problemas-que-iac-resolve","Os problemas que IaC resolve",[125,126,127,140],"table",{},[128,129,130],"thead",{},[131,132,133,137],"tr",{},[134,135,136],"th",{},"Problema (sem IaC)",[134,138,139],{},"Solução (com IaC)",[141,142,143,152,160,168,176],"tbody",{},[131,144,145,149],{},[146,147,148],"td",{},"\"Como criamos esse servidor?\" — ninguém lembra",[146,150,151],{},"Tudo está no código, versionado no Git",[131,153,154,157],{},[146,155,156],{},"Recriar o ambiente de teste leva 2 dias",[146,158,159],{},"Um comando recria tudo em minutos",[131,161,162,165],{},[146,163,164],{},"Um dev configura diferente do outro",[146,166,167],{},"O código é a fonte da verdade, idempotente",[131,169,170,173],{},[146,171,172],{},"Mudança manual quebra algo e ninguém sabe o quê",[146,174,175],{},"Mudanças passam por code review",[131,177,178,181],{},[146,179,180],{},"Auditoria de compliance é impossível",[146,182,183],{},"O histórico do Git é a auditoria",[73,185,186,189],{},[81,187,188],{},"Idempotente"," é uma palavra importante aqui: significa que executar o mesmo\ncomando várias vezes produz o mesmo resultado. Se você pedir \"crie um servidor\nchamado web-01\" e ele já existe, o Terraform não cria outro — ele reconhece\nque já está lá e não faz nada. Isso evita duplicações acidentais.",[11,191,193],{"id":192},"por-que-terraform-por-que-terraform","Por que Terraform {#por-que-terraform}",[73,195,196],{},"Existem várias ferramentas de IaC no mercado. As principais são:",[125,198,199,215],{},[128,200,201],{},[131,202,203,206,209,212],{},[134,204,205],{},"Ferramenta",[134,207,208],{},"Criador",[134,210,211],{},"Estilo",[134,213,214],{},"Cloud-agnostic?",[141,216,217,233,248,262],{},[131,218,219,224,227,230],{},[146,220,221],{},[81,222,223],{},"Terraform",[146,225,226],{},"HashiCorp",[146,228,229],{},"Declarativo",[146,231,232],{},"Sim",[131,234,235,240,243,245],{},[146,236,237],{},[81,238,239],{},"AWS CloudFormation",[146,241,242],{},"Amazon",[146,244,229],{},[146,246,247],{},"Só AWS",[131,249,250,255,257,260],{},[146,251,252],{},[81,253,254],{},"Pulumi",[146,256,254],{},[146,258,259],{},"Imperativo (linguagens reais)",[146,261,232],{},[131,263,264,269,272,275],{},[146,265,266],{},[81,267,268],{},"Ansible",[146,270,271],{},"Red Hat",[146,273,274],{},"Procedural\u002FDeclarativo",[146,276,277],{},"Sim (mais config mgmt)",[73,279,280,282],{},[81,281,223],{}," é a ferramenta mais popular de IaC. Algumas razões:",[284,285,286,299,305,311],"ul",{},[19,287,288,290,291,294,295,298],{},[81,289,229],{},": você descreve ",[99,292,293],{},"o que"," quer (um servidor com 4GB de RAM),\nnão ",[99,296,297],{},"como"," chegar lá (os 15 cliques no painel). O Terraform descobre o\n\"como\".",[19,300,301,304],{},[81,302,303],{},"Cloud-agnostic"," (independente de nuvem): o mesmo Terraform gerencia AWS,\nGoogle Cloud, Azure, e mais de 3.000 outros provedores. Aprende uma vez,\nusa em qualquer nuvem.",[19,306,307,310],{},[81,308,309],{},"Gratuito e open source",": a versão OpenTofu (fork da comunidade) é 100%\ngratuita. A HashiCorp oferece versão paga com features enterprise.",[19,312,313,316],{},[81,314,315],{},"Comunidade gigante",": milhares de módulos prontos para usar.",[120,318,320],{"id":319},"declarativo-vs-imperativo","Declarativo vs imperativo",[73,322,323,325],{},[81,324,229],{}," (Terraform): você diz o resultado final que quer.",[327,328,333],"pre",{"className":329,"code":330,"language":331,"meta":332,"style":332},"language-hcl shiki shiki-themes github-light github-dark","# \"Quero um servidor EC2 com esta configuração\"\nresource \"aws_instance\" \"web\" {\n  ami           = \"ami-123456\"\n  instance_type = \"t3.micro\"\n}\n","hcl","",[334,335,336,344,350,356,362],"code",{"__ignoreMap":332},[337,338,341],"span",{"class":339,"line":340},"line",1,[337,342,343],{},"# \"Quero um servidor EC2 com esta configuração\"\n",[337,345,347],{"class":339,"line":346},2,[337,348,349],{},"resource \"aws_instance\" \"web\" {\n",[337,351,353],{"class":339,"line":352},3,[337,354,355],{},"  ami           = \"ami-123456\"\n",[337,357,359],{"class":339,"line":358},4,[337,360,361],{},"  instance_type = \"t3.micro\"\n",[337,363,365],{"class":339,"line":364},5,[337,366,367],{},"}\n",[73,369,370,373],{},[81,371,372],{},"Imperativo"," (scripts Bash, por exemplo): você diz cada passo.",[327,375,379],{"className":376,"code":377,"language":378,"meta":332,"style":332},"language-bash shiki shiki-themes github-light github-dark","# \"Faça isto, depois aquilo, depois aquilo outro\"\naws ec2 run-instances --image-id ami-123456 --instance-type t3.micro\naws ec2 create-tags --resources i-abc123 --tags Key=Name,Value=web\naws ec2 modify-instance-attribute --instance-id i-abc123 ...\n","bash",[334,380,381,387,413,434],{"__ignoreMap":332},[337,382,383],{"class":339,"line":340},[337,384,386],{"class":385},"sJ8bj","# \"Faça isto, depois aquilo, depois aquilo outro\"\n",[337,388,389,393,397,400,404,407,410],{"class":339,"line":346},[337,390,392],{"class":391},"sScJk","aws",[337,394,396],{"class":395},"sZZnC"," ec2",[337,398,399],{"class":395}," run-instances",[337,401,403],{"class":402},"sj4cs"," --image-id",[337,405,406],{"class":395}," ami-123456",[337,408,409],{"class":402}," --instance-type",[337,411,412],{"class":395}," t3.micro\n",[337,414,415,417,419,422,425,428,431],{"class":339,"line":352},[337,416,392],{"class":391},[337,418,396],{"class":395},[337,420,421],{"class":395}," create-tags",[337,423,424],{"class":402}," --resources",[337,426,427],{"class":395}," i-abc123",[337,429,430],{"class":402}," --tags",[337,432,433],{"class":395}," Key=Name,Value=web\n",[337,435,436,438,440,443,446,448],{"class":339,"line":358},[337,437,392],{"class":391},[337,439,396],{"class":395},[337,441,442],{"class":395}," modify-instance-attribute",[337,444,445],{"class":402}," --instance-id",[337,447,427],{"class":395},[337,449,450],{"class":395}," ...\n",[73,452,453],{},"O estilo declarativo é melhor para infraestrutura porque você não precisa\nrastrear o estado atual — apenas declara o desejado e a ferramenta calcula a\ndiferença.",[11,455,457],{"id":456},"conceitos-essenciais-conceitos","Conceitos essenciais {#conceitos}",[73,459,460],{},"Antes de escrever código, entenda estes quatro conceitos:",[120,462,464],{"id":463},"_1-provider-provedor","1. Provider (provedor)",[73,466,467,468,471],{},"Um provider é um ",[81,469,470],{},"plugin"," que permite ao Terraform falar com um serviço.\nExiste um provider para AWS, um para Google Cloud, um para GitHub, um para\nKubernetes, etc. O provider traduz os comandos do Terraform em chamadas de\nAPI do serviço.",[120,473,475],{"id":474},"_2-resource-recurso","2. Resource (recurso)",[73,477,478,479,482],{},"Um resource é a ",[81,480,481],{},"unidade básica"," de infraestrutura. Um servidor, um banco de\ndados, uma regra de firewall, um bucket de armazenamento — cada um é um\nresource. A maioria dos seus arquivos Terraform será composta de resources.",[120,484,486],{"id":485},"_3-state-estado","3. State (estado)",[73,488,489,490,493,494,497],{},"O ",[81,491,492],{},"state"," é um arquivo (",[334,495,496],{},".tfstate",") que registra o mapeamento entre o que\nestá no seu código e o que existe na nuvem. É a \"memória\" do Terraform.",[73,499,500],{},"Por que o state é necessário? Porque o Terraform é declarativo e idempotente.\nPara saber se precisa criar, modificar ou destruir algo, ele compara:",[284,502,503,506,509],{},[19,504,505],{},"O que está no seu código (estado desejado)",[19,507,508],{},"O que está no state (o que ele criou da última vez)",[19,510,511],{},"O que está na nuvem (estado real)",[73,513,514],{},"Sem o state, o Terraform não conseguiria saber se aquele servidor foi criado\npor ele ou por outra pessoa.",[120,516,518],{"id":517},"_4-plan-e-apply","4. Plan e Apply",[73,520,521],{},"Terraform opera em dois passos principais:",[284,523,524,536],{},[19,525,526,531,532,535],{},[81,527,528],{},[334,529,530],{},"terraform plan",": mostra o que ",[99,533,534],{},"vai"," fazer, sem fazer nada. É uma\nsimulação. \"Vou criar 1 servidor, 1 banco de dados, e destruir 1 regra de\nfirewall antiga.\" Você revisa antes de prosseguir.",[19,537,538,543],{},[81,539,540],{},[334,541,542],{},"terraform apply",": executa de fato as mudanças mostradas no plan.",[73,545,546,549,550,553,554,557],{},[81,547,548],{},"Analogia",": ",[334,551,552],{},"plan"," é o orçamento que o arquiteto te mostra antes de\nconstruir. ",[334,555,556],{},"apply"," é quando você aprova e a construtora começa a obra.",[11,559,561],{"id":560},"sua-primeira-infraestrutura-com-terraform-primeira-infra","Sua primeira infraestrutura com Terraform {#primeira-infra}",[73,563,564,565,568],{},"Vamos criar um servidor EC2 na AWS. ",[81,566,567],{},"EC2"," (Elastic Compute Cloud) é o\nserviço de servidores virtuais da AWS — basicamente, um computador que você\naluga na nuvem.",[120,570,572],{"id":571},"pré-requisitos","Pré-requisitos",[16,574,575,581,595],{},[19,576,577,580],{},[81,578,579],{},"Terraform instalado"," (versão 1.0+)",[19,582,583,586,587,590,591,594],{},[81,584,585],{},"Conta na AWS"," com credenciais configuradas (variáveis de ambiente\n",[334,588,589],{},"AWS_ACCESS_KEY_ID"," e ",[334,592,593],{},"AWS_SECRET_ACCESS_KEY",")",[19,596,597],{},"Um editor de texto",[120,599,601,602],{"id":600},"passo-1-criar-o-arquivo-maintf","Passo 1: criar o arquivo ",[334,603,604],{},"main.tf",[327,606,608],{"className":329,"code":607,"language":331,"meta":332,"style":332},"# main.tf — arquivo principal do Terraform\n\n# Diz ao Terraform que vamos usar a AWS como provedor\nterraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp\u002Faws\"  # Onde baixar o provider\n      version = \"~> 5.0\"         # Versão 5.x (qualquer 5.algo)\n    }\n  }\n}\n\n# Configura o provider da AWS\nprovider \"aws\" {\n  region = \"us-east-1\"  # Norte da Virgínia — a região mais barata da AWS\n}\n\n# Cria um servidor EC2\n# \"aws_instance\" é o tipo do resource (uma instância EC2)\n# \"web\" é o nome lógico que damos (para referenciar depois)\nresource \"aws_instance\" \"web\" {\n  ami           = \"ami-0c7217cdde317cfec\"  # ID da imagem (Amazon Linux 2023)\n  instance_type = \"t3.micro\"               # Tamanho: 2 vCPUs, 1GB RAM\n\n  tags = {\n    Name        = \"meu-primeiro-servidor\"   # Nome que aparece no painel AWS\n    Environment = \"dev\"                    # Tag para organizar recursos\n    Owner       = \"inicialize\"\n  }\n}\n",[334,609,610,615,621,626,631,636,642,648,654,660,666,671,676,682,688,694,699,704,710,716,722,727,733,739,744,750,756,762,768,773],{"__ignoreMap":332},[337,611,612],{"class":339,"line":340},[337,613,614],{},"# main.tf — arquivo principal do Terraform\n",[337,616,617],{"class":339,"line":346},[337,618,620],{"emptyLinePlaceholder":619},true,"\n",[337,622,623],{"class":339,"line":352},[337,624,625],{},"# Diz ao Terraform que vamos usar a AWS como provedor\n",[337,627,628],{"class":339,"line":358},[337,629,630],{},"terraform {\n",[337,632,633],{"class":339,"line":364},[337,634,635],{},"  required_providers {\n",[337,637,639],{"class":339,"line":638},6,[337,640,641],{},"    aws = {\n",[337,643,645],{"class":339,"line":644},7,[337,646,647],{},"      source  = \"hashicorp\u002Faws\"  # Onde baixar o provider\n",[337,649,651],{"class":339,"line":650},8,[337,652,653],{},"      version = \"~> 5.0\"         # Versão 5.x (qualquer 5.algo)\n",[337,655,657],{"class":339,"line":656},9,[337,658,659],{},"    }\n",[337,661,663],{"class":339,"line":662},10,[337,664,665],{},"  }\n",[337,667,669],{"class":339,"line":668},11,[337,670,367],{},[337,672,674],{"class":339,"line":673},12,[337,675,620],{"emptyLinePlaceholder":619},[337,677,679],{"class":339,"line":678},13,[337,680,681],{},"# Configura o provider da AWS\n",[337,683,685],{"class":339,"line":684},14,[337,686,687],{},"provider \"aws\" {\n",[337,689,691],{"class":339,"line":690},15,[337,692,693],{},"  region = \"us-east-1\"  # Norte da Virgínia — a região mais barata da AWS\n",[337,695,697],{"class":339,"line":696},16,[337,698,367],{},[337,700,702],{"class":339,"line":701},17,[337,703,620],{"emptyLinePlaceholder":619},[337,705,707],{"class":339,"line":706},18,[337,708,709],{},"# Cria um servidor EC2\n",[337,711,713],{"class":339,"line":712},19,[337,714,715],{},"# \"aws_instance\" é o tipo do resource (uma instância EC2)\n",[337,717,719],{"class":339,"line":718},20,[337,720,721],{},"# \"web\" é o nome lógico que damos (para referenciar depois)\n",[337,723,725],{"class":339,"line":724},21,[337,726,349],{},[337,728,730],{"class":339,"line":729},22,[337,731,732],{},"  ami           = \"ami-0c7217cdde317cfec\"  # ID da imagem (Amazon Linux 2023)\n",[337,734,736],{"class":339,"line":735},23,[337,737,738],{},"  instance_type = \"t3.micro\"               # Tamanho: 2 vCPUs, 1GB RAM\n",[337,740,742],{"class":339,"line":741},24,[337,743,620],{"emptyLinePlaceholder":619},[337,745,747],{"class":339,"line":746},25,[337,748,749],{},"  tags = {\n",[337,751,753],{"class":339,"line":752},26,[337,754,755],{},"    Name        = \"meu-primeiro-servidor\"   # Nome que aparece no painel AWS\n",[337,757,759],{"class":339,"line":758},27,[337,760,761],{},"    Environment = \"dev\"                    # Tag para organizar recursos\n",[337,763,765],{"class":339,"line":764},28,[337,766,767],{},"    Owner       = \"inicialize\"\n",[337,769,771],{"class":339,"line":770},29,[337,772,665],{},[337,774,776],{"class":339,"line":775},30,[337,777,367],{},[120,779,781],{"id":780},"passo-2-inicializar-o-terraform","Passo 2: inicializar o Terraform",[327,783,785],{"className":376,"code":784,"language":378,"meta":332,"style":332},"terraform init\n",[334,786,787],{"__ignoreMap":332},[337,788,789,792],{"class":339,"line":340},[337,790,791],{"class":391},"terraform",[337,793,794],{"class":395}," init\n",[73,796,797],{},"Este comando baixa o provider da AWS e prepara o diretório. Você verá algo\ncomo \"Terraform has been successfully initialized!\".",[120,799,801],{"id":800},"passo-3-ver-o-plano-simulação","Passo 3: ver o plano (simulação)",[327,803,805],{"className":376,"code":804,"language":378,"meta":332,"style":332},"terraform plan\n",[334,806,807],{"__ignoreMap":332},[337,808,809,811],{"class":339,"line":340},[337,810,791],{"class":391},[337,812,813],{"class":395}," plan\n",[73,815,816],{},"O Terraform vai mostrar:",[327,818,823],{"className":819,"code":821,"language":822},[820],"language-text","Terraform will perform the following actions:\n\n  # aws_instance.web will be created\n  + resource \"aws_instance\" \"web\" {\n      + ami           = \"ami-0c7217cdde317cfec\"\n      + instance_type = \"t3.micro\"\n      + tags          = {\n          + Environment = \"dev\"\n          + Name        = \"meu-primeiro-servidor\"\n          + Owner       = \"inicialize\"\n        }\n    }\n\nPlan: 1 to add, 0 to change, 0 to destroy.\n","text",[334,824,821],{"__ignoreMap":332},[73,826,827,828,831,832,835,836,839],{},"O símbolo ",[334,829,830],{},"+"," significa \"criar\". Se fosse ",[334,833,834],{},"~"," seria \"modificar\", e ",[334,837,838],{},"-"," seria\n\"destruir\". Revise com calma — especialmente o número de \"destroy\".",[120,841,843],{"id":842},"passo-4-aplicar-executar-de-verdade","Passo 4: aplicar (executar de verdade)",[327,845,847],{"className":376,"code":846,"language":378,"meta":332,"style":332},"terraform apply\n",[334,848,849],{"__ignoreMap":332},[337,850,851,853],{"class":339,"line":340},[337,852,791],{"class":391},[337,854,855],{"class":395}," apply\n",[73,857,858,859,862],{},"O Terraform pede confirmação (\"Do you want to perform these actions?\"). Digite\n",[334,860,861],{},"yes",". Em segundos, seu servidor está rodando na AWS.",[120,864,866],{"id":865},"passo-5-destruir-para-não-pagar","Passo 5: destruir (para não pagar)",[327,868,870],{"className":376,"code":869,"language":378,"meta":332,"style":332},"terraform destroy\n",[334,871,872],{"__ignoreMap":332},[337,873,874,876],{"class":339,"line":340},[337,875,791],{"class":391},[337,877,878],{"class":395}," destroy\n",[73,880,881,884,885,887],{},[81,882,883],{},"Importante",": este comando remove tudo o que o Terraform criou. Use-o quando\nterminar de testar para não gerar custos desnecessários. Digite ",[334,886,861],{}," para\nconfirmar.",[11,889,891],{"id":890},"variáveis-reutilização-e-flexibilidade-variaveis","Variáveis: reutilização e flexibilidade {#variaveis}",[73,893,894,895,898],{},"No exemplo anterior, a região e o tipo da instância estavam \"fixos\" no código.\nPara reutilizar o mesmo código em diferentes ambientes (dev, produção), usamos\n",[81,896,897],{},"variáveis",".",[327,900,902],{"className":329,"code":901,"language":331,"meta":332,"style":332},"# variables.tf — declara as variáveis\n\nvariable \"aws_region\" {\n  description = \"Região da AWS onde os recursos serão criados\"\n  type        = string\n  default     = \"us-east-1\"  # Valor padrão, se não for passado\n}\n\nvariable \"instance_type\" {\n  description = \"Tipo da instância EC2\"\n  type        = string\n  default     = \"t3.micro\"\n}\n\nvariable \"environment\" {\n  description = \"Nome do ambiente (dev, staging, prod)\"\n  type        = string\n  default     = \"dev\"\n}\n",[334,903,904,909,913,918,923,928,933,937,941,946,951,955,960,964,968,973,978,982,987],{"__ignoreMap":332},[337,905,906],{"class":339,"line":340},[337,907,908],{},"# variables.tf — declara as variáveis\n",[337,910,911],{"class":339,"line":346},[337,912,620],{"emptyLinePlaceholder":619},[337,914,915],{"class":339,"line":352},[337,916,917],{},"variable \"aws_region\" {\n",[337,919,920],{"class":339,"line":358},[337,921,922],{},"  description = \"Região da AWS onde os recursos serão criados\"\n",[337,924,925],{"class":339,"line":364},[337,926,927],{},"  type        = string\n",[337,929,930],{"class":339,"line":638},[337,931,932],{},"  default     = \"us-east-1\"  # Valor padrão, se não for passado\n",[337,934,935],{"class":339,"line":644},[337,936,367],{},[337,938,939],{"class":339,"line":650},[337,940,620],{"emptyLinePlaceholder":619},[337,942,943],{"class":339,"line":656},[337,944,945],{},"variable \"instance_type\" {\n",[337,947,948],{"class":339,"line":662},[337,949,950],{},"  description = \"Tipo da instância EC2\"\n",[337,952,953],{"class":339,"line":668},[337,954,927],{},[337,956,957],{"class":339,"line":673},[337,958,959],{},"  default     = \"t3.micro\"\n",[337,961,962],{"class":339,"line":678},[337,963,367],{},[337,965,966],{"class":339,"line":684},[337,967,620],{"emptyLinePlaceholder":619},[337,969,970],{"class":339,"line":690},[337,971,972],{},"variable \"environment\" {\n",[337,974,975],{"class":339,"line":696},[337,976,977],{},"  description = \"Nome do ambiente (dev, staging, prod)\"\n",[337,979,980],{"class":339,"line":701},[337,981,927],{},[337,983,984],{"class":339,"line":706},[337,985,986],{},"  default     = \"dev\"\n",[337,988,989],{"class":339,"line":712},[337,990,367],{},[327,992,994],{"className":329,"code":993,"language":331,"meta":332,"style":332},"# main.tf — usando as variáveis\n\nprovider \"aws\" {\n  region = var.aws_region  # Referência à variável com var.NOME\n}\n\nresource \"aws_instance\" \"web\" {\n  ami           = \"ami-0c7217cdde317cfec\"\n  instance_type = var.instance_type\n\n  tags = {\n    Name        = \"web-${var.environment}\"  # Interpolação: web-dev, web-prod\n    Environment = var.environment\n  }\n}\n",[334,995,996,1001,1005,1009,1014,1018,1022,1026,1031,1036,1040,1044,1049,1054,1058],{"__ignoreMap":332},[337,997,998],{"class":339,"line":340},[337,999,1000],{},"# main.tf — usando as variáveis\n",[337,1002,1003],{"class":339,"line":346},[337,1004,620],{"emptyLinePlaceholder":619},[337,1006,1007],{"class":339,"line":352},[337,1008,687],{},[337,1010,1011],{"class":339,"line":358},[337,1012,1013],{},"  region = var.aws_region  # Referência à variável com var.NOME\n",[337,1015,1016],{"class":339,"line":364},[337,1017,367],{},[337,1019,1020],{"class":339,"line":638},[337,1021,620],{"emptyLinePlaceholder":619},[337,1023,1024],{"class":339,"line":644},[337,1025,349],{},[337,1027,1028],{"class":339,"line":650},[337,1029,1030],{},"  ami           = \"ami-0c7217cdde317cfec\"\n",[337,1032,1033],{"class":339,"line":656},[337,1034,1035],{},"  instance_type = var.instance_type\n",[337,1037,1038],{"class":339,"line":662},[337,1039,620],{"emptyLinePlaceholder":619},[337,1041,1042],{"class":339,"line":668},[337,1043,749],{},[337,1045,1046],{"class":339,"line":673},[337,1047,1048],{},"    Name        = \"web-${var.environment}\"  # Interpolação: web-dev, web-prod\n",[337,1050,1051],{"class":339,"line":678},[337,1052,1053],{},"    Environment = var.environment\n",[337,1055,1056],{"class":339,"line":684},[337,1057,665],{},[337,1059,1060],{"class":339,"line":690},[337,1061,367],{},[73,1063,1064],{},"Para passar valores diferentes na linha de comando:",[327,1066,1068],{"className":376,"code":1067,"language":378,"meta":332,"style":332},"# Cria um servidor maior em produção\nterraform apply -var=\"instance_type=t3.large\" -var=\"environment=prod\"\n",[334,1069,1070,1075],{"__ignoreMap":332},[337,1071,1072],{"class":339,"line":340},[337,1073,1074],{"class":385},"# Cria um servidor maior em produção\n",[337,1076,1077,1079,1082,1085,1088,1090],{"class":339,"line":346},[337,1078,791],{"class":391},[337,1080,1081],{"class":395}," apply",[337,1083,1084],{"class":402}," -var=",[337,1086,1087],{"class":395},"\"instance_type=t3.large\"",[337,1089,1084],{"class":402},[337,1091,1092],{"class":395},"\"environment=prod\"\n",[73,1094,1095,1096,1099],{},"Ou crie um arquivo ",[334,1097,1098],{},"terraform.tfvars",":",[327,1101,1103],{"className":329,"code":1102,"language":331,"meta":332,"style":332},"# terraform.tfvars — valores específicos por ambiente\ninstance_type = \"t3.large\"\nenvironment   = \"prod\"\naws_region    = \"sa-east-1\"  # São Paulo (mais caro, mas menor latência no Brasil)\n",[334,1104,1105,1110,1115,1120],{"__ignoreMap":332},[337,1106,1107],{"class":339,"line":340},[337,1108,1109],{},"# terraform.tfvars — valores específicos por ambiente\n",[337,1111,1112],{"class":339,"line":346},[337,1113,1114],{},"instance_type = \"t3.large\"\n",[337,1116,1117],{"class":339,"line":352},[337,1118,1119],{},"environment   = \"prod\"\n",[337,1121,1122],{"class":339,"line":358},[337,1123,1124],{},"aws_region    = \"sa-east-1\"  # São Paulo (mais caro, mas menor latência no Brasil)\n",[11,1126,1128],{"id":1127},"state-a-memória-do-terraform-state","State: a memória do Terraform {#state}",[73,1130,1131,1132,1135],{},"O arquivo de state (",[334,1133,1134],{},"terraform.tfstate",") é crítico. Se você o perder, o\nTerraform perde a noção do que criou — e pode duplicar recursos ou falhar ao\ndestruir.",[120,1137,1139],{"id":1138},"regras-de-ouro-do-state","Regras de ouro do state",[16,1141,1142,1151,1157],{},[19,1143,1144,1150],{},[81,1145,1146,1147,1149],{},"Nunca edite o ",[334,1148,496],{}," manualmente",". Sempre use comandos do Terraform.",[19,1152,1153,1156],{},[81,1154,1155],{},"Sempre armazene"," o state remotamente, não localmente.",[19,1158,1159,1162],{},[81,1160,1161],{},"Sempre trave"," o state durante uso (locking) para evitar corrupção.",[120,1164,1166],{"id":1165},"remote-state-state-remoto","Remote state (state remoto)",[73,1168,1169,1170,1173,1174,1177],{},"Para times, o state deve ficar em um local compartilhado com bloqueio (lock).\nNa AWS, usamos um ",[81,1171,1172],{},"bucket S3"," com uma tabela ",[81,1175,1176],{},"DynamoDB"," para lock.",[73,1179,1180],{},"S3 é o serviço de armazenamento de arquivos da AWS. DynamoDB é um banco de\ndados NoSQL da AWS — neste caso, usado só para gerenciar locks.",[327,1182,1184],{"className":329,"code":1183,"language":331,"meta":332,"style":332},"# backend.tf — configura onde o state é guardado\n\nterraform {\n  backend \"s3\" {\n    bucket         = \"meu-terraform-state-dev\"  # Bucket S3 que guarda o state\n    key            = \"infra\u002Fterraform.tfstate\"  # Caminho do arquivo dentro do bucket\n    region         = \"us-east-1\"                # Região do bucket\n    dynamodb_table = \"terraform-locks\"          # Tabela para lock (evita edição simultânea)\n    encrypt        = true                       # Criptografa o state em repouso\n  }\n}\n",[334,1185,1186,1191,1195,1199,1204,1209,1214,1219,1224,1229,1233],{"__ignoreMap":332},[337,1187,1188],{"class":339,"line":340},[337,1189,1190],{},"# backend.tf — configura onde o state é guardado\n",[337,1192,1193],{"class":339,"line":346},[337,1194,620],{"emptyLinePlaceholder":619},[337,1196,1197],{"class":339,"line":352},[337,1198,630],{},[337,1200,1201],{"class":339,"line":358},[337,1202,1203],{},"  backend \"s3\" {\n",[337,1205,1206],{"class":339,"line":364},[337,1207,1208],{},"    bucket         = \"meu-terraform-state-dev\"  # Bucket S3 que guarda o state\n",[337,1210,1211],{"class":339,"line":638},[337,1212,1213],{},"    key            = \"infra\u002Fterraform.tfstate\"  # Caminho do arquivo dentro do bucket\n",[337,1215,1216],{"class":339,"line":644},[337,1217,1218],{},"    region         = \"us-east-1\"                # Região do bucket\n",[337,1220,1221],{"class":339,"line":650},[337,1222,1223],{},"    dynamodb_table = \"terraform-locks\"          # Tabela para lock (evita edição simultânea)\n",[337,1225,1226],{"class":339,"line":656},[337,1227,1228],{},"    encrypt        = true                       # Criptografa o state em repouso\n",[337,1230,1231],{"class":339,"line":662},[337,1232,665],{},[337,1234,1235],{"class":339,"line":668},[337,1236,367],{},[1238,1239,1240],"blockquote",{},[73,1241,1242,1245,1246,1249,1250,1253],{},[81,1243,1244],{},"Atenção",": o bucket S3 e a tabela DynamoDB precisam existir ",[81,1247,1248],{},"antes"," de\nrodar ",[334,1251,1252],{},"terraform init"," com o backend remoto. Crie-os manualmente uma única\nvez (ou use um projeto Terraform separado para o backend).",[120,1255,1257],{"id":1256},"por-que-lock-é-importante","Por que lock é importante?",[73,1259,1260,1261,1263],{},"Se dois desenvolvedores rodarem ",[334,1262,542],{}," ao mesmo tempo, ambos leem o\nstate, fazem mudanças, e o segundo sobrescreve o primeiro — corrompendo o\nstate. O lock (via DynamoDB) impede isso: o primeiro trava, o segundo espera.",[11,1265,1267],{"id":1266},"módulos-organização-em-larga-escala-modulos","Módulos: organização em larga escala {#modulos}",[73,1269,1270,1271,1273,1274,1277],{},"Quando sua infraestrutura cresce (10, 50, 100 resources), um único ",[334,1272,604],{},"\nfica impossível de manter. ",[81,1275,1276],{},"Módulos"," são a solução: pacotes reutilizáveis de\nconfiguração Terraform.",[73,1279,1280,1282],{},[81,1281,548],{},": um módulo é como uma função em programação. Em vez de repetir o\ncódigo do servidor em cada ambiente, você cria um módulo \"servidor-web\" e o\nchama com parâmetros diferentes.",[120,1284,1286],{"id":1285},"estrutura-de-um-módulo","Estrutura de um módulo",[327,1288,1291],{"className":1289,"code":1290,"language":822},[820],"projeto\u002F\n├── main.tf          # Chama os módulos\n├── variables.tf     # Variáveis do projeto\n├── modules\u002F\n│   └── web-server\u002F  # Módulo reutilizável\n│       ├── main.tf       # Define os resources do módulo\n│       ├── variables.tf  # Inputs do módulo\n│       └── outputs.tf    # Outputs do módulo (valores que retorna)\n",[334,1292,1290],{"__ignoreMap":332},[327,1294,1296],{"className":329,"code":1295,"language":331,"meta":332,"style":332},"# modules\u002Fweb-server\u002Fmain.tf — conteúdo do módulo\n\nvariable \"instance_type\" {\n  type    = string\n  default = \"t3.micro\"\n}\n\nvariable \"environment\" {\n  type = string\n}\n\nvariable \"app_name\" {\n  type = string\n}\n\nresource \"aws_instance\" \"web\" {\n  ami           = \"ami-0c7217cdde317cfec\"\n  instance_type = var.instance_type\n\n  tags = {\n    Name        = \"${var.app_name}-${var.environment}\"\n    Environment = var.environment\n  }\n}\n\n# Outputs: valores que o módulo retorna para quem o chamou\noutput \"instance_id\" {\n  value       = aws_instance.web.id\n  description = \"ID da instância criada\"\n}\n\noutput \"public_ip\" {\n  value       = aws_instance.web.public_ip\n  description = \"IP público do servidor\"\n}\n",[334,1297,1298,1303,1307,1311,1316,1321,1325,1329,1333,1338,1342,1346,1351,1355,1359,1363,1367,1371,1375,1379,1383,1388,1392,1396,1400,1404,1409,1414,1419,1424,1428,1433,1439,1445,1451],{"__ignoreMap":332},[337,1299,1300],{"class":339,"line":340},[337,1301,1302],{},"# modules\u002Fweb-server\u002Fmain.tf — conteúdo do módulo\n",[337,1304,1305],{"class":339,"line":346},[337,1306,620],{"emptyLinePlaceholder":619},[337,1308,1309],{"class":339,"line":352},[337,1310,945],{},[337,1312,1313],{"class":339,"line":358},[337,1314,1315],{},"  type    = string\n",[337,1317,1318],{"class":339,"line":364},[337,1319,1320],{},"  default = \"t3.micro\"\n",[337,1322,1323],{"class":339,"line":638},[337,1324,367],{},[337,1326,1327],{"class":339,"line":644},[337,1328,620],{"emptyLinePlaceholder":619},[337,1330,1331],{"class":339,"line":650},[337,1332,972],{},[337,1334,1335],{"class":339,"line":656},[337,1336,1337],{},"  type = string\n",[337,1339,1340],{"class":339,"line":662},[337,1341,367],{},[337,1343,1344],{"class":339,"line":668},[337,1345,620],{"emptyLinePlaceholder":619},[337,1347,1348],{"class":339,"line":673},[337,1349,1350],{},"variable \"app_name\" {\n",[337,1352,1353],{"class":339,"line":678},[337,1354,1337],{},[337,1356,1357],{"class":339,"line":684},[337,1358,367],{},[337,1360,1361],{"class":339,"line":690},[337,1362,620],{"emptyLinePlaceholder":619},[337,1364,1365],{"class":339,"line":696},[337,1366,349],{},[337,1368,1369],{"class":339,"line":701},[337,1370,1030],{},[337,1372,1373],{"class":339,"line":706},[337,1374,1035],{},[337,1376,1377],{"class":339,"line":712},[337,1378,620],{"emptyLinePlaceholder":619},[337,1380,1381],{"class":339,"line":718},[337,1382,749],{},[337,1384,1385],{"class":339,"line":724},[337,1386,1387],{},"    Name        = \"${var.app_name}-${var.environment}\"\n",[337,1389,1390],{"class":339,"line":729},[337,1391,1053],{},[337,1393,1394],{"class":339,"line":735},[337,1395,665],{},[337,1397,1398],{"class":339,"line":741},[337,1399,367],{},[337,1401,1402],{"class":339,"line":746},[337,1403,620],{"emptyLinePlaceholder":619},[337,1405,1406],{"class":339,"line":752},[337,1407,1408],{},"# Outputs: valores que o módulo retorna para quem o chamou\n",[337,1410,1411],{"class":339,"line":758},[337,1412,1413],{},"output \"instance_id\" {\n",[337,1415,1416],{"class":339,"line":764},[337,1417,1418],{},"  value       = aws_instance.web.id\n",[337,1420,1421],{"class":339,"line":770},[337,1422,1423],{},"  description = \"ID da instância criada\"\n",[337,1425,1426],{"class":339,"line":775},[337,1427,367],{},[337,1429,1431],{"class":339,"line":1430},31,[337,1432,620],{"emptyLinePlaceholder":619},[337,1434,1436],{"class":339,"line":1435},32,[337,1437,1438],{},"output \"public_ip\" {\n",[337,1440,1442],{"class":339,"line":1441},33,[337,1443,1444],{},"  value       = aws_instance.web.public_ip\n",[337,1446,1448],{"class":339,"line":1447},34,[337,1449,1450],{},"  description = \"IP público do servidor\"\n",[337,1452,1454],{"class":339,"line":1453},35,[337,1455,367],{},[327,1457,1459],{"className":329,"code":1458,"language":331,"meta":332,"style":332},"# main.tf — usando o módulo no projeto principal\n\nmodule \"web_dev\" {\n  source        = \".\u002Fmodules\u002Fweb-server\"  # Caminho para o módulo\n  app_name      = \"blog\"\n  environment   = \"dev\"\n  instance_type = \"t3.micro\"\n}\n\nmodule \"web_prod\" {\n  source        = \".\u002Fmodules\u002Fweb-server\"  # Mesmo módulo, parâmetros diferentes\n  app_name      = \"blog\"\n  environment   = \"prod\"\n  instance_type = \"t3.large\"              # Produção merece mais recursos\n}\n\n# Acessando os outputs do módulo\noutput \"ip_producao\" {\n  value = module.web_prod.public_ip  # Pega o IP público do módulo de prod\n}\n",[334,1460,1461,1466,1470,1475,1480,1485,1490,1494,1498,1502,1507,1512,1516,1521,1526,1530,1534,1539,1544,1549],{"__ignoreMap":332},[337,1462,1463],{"class":339,"line":340},[337,1464,1465],{},"# main.tf — usando o módulo no projeto principal\n",[337,1467,1468],{"class":339,"line":346},[337,1469,620],{"emptyLinePlaceholder":619},[337,1471,1472],{"class":339,"line":352},[337,1473,1474],{},"module \"web_dev\" {\n",[337,1476,1477],{"class":339,"line":358},[337,1478,1479],{},"  source        = \".\u002Fmodules\u002Fweb-server\"  # Caminho para o módulo\n",[337,1481,1482],{"class":339,"line":364},[337,1483,1484],{},"  app_name      = \"blog\"\n",[337,1486,1487],{"class":339,"line":638},[337,1488,1489],{},"  environment   = \"dev\"\n",[337,1491,1492],{"class":339,"line":644},[337,1493,361],{},[337,1495,1496],{"class":339,"line":650},[337,1497,367],{},[337,1499,1500],{"class":339,"line":656},[337,1501,620],{"emptyLinePlaceholder":619},[337,1503,1504],{"class":339,"line":662},[337,1505,1506],{},"module \"web_prod\" {\n",[337,1508,1509],{"class":339,"line":668},[337,1510,1511],{},"  source        = \".\u002Fmodules\u002Fweb-server\"  # Mesmo módulo, parâmetros diferentes\n",[337,1513,1514],{"class":339,"line":673},[337,1515,1484],{},[337,1517,1518],{"class":339,"line":678},[337,1519,1520],{},"  environment   = \"prod\"\n",[337,1522,1523],{"class":339,"line":684},[337,1524,1525],{},"  instance_type = \"t3.large\"              # Produção merece mais recursos\n",[337,1527,1528],{"class":339,"line":690},[337,1529,367],{},[337,1531,1532],{"class":339,"line":696},[337,1533,620],{"emptyLinePlaceholder":619},[337,1535,1536],{"class":339,"line":701},[337,1537,1538],{},"# Acessando os outputs do módulo\n",[337,1540,1541],{"class":339,"line":706},[337,1542,1543],{},"output \"ip_producao\" {\n",[337,1545,1546],{"class":339,"line":712},[337,1547,1548],{},"  value = module.web_prod.public_ip  # Pega o IP público do módulo de prod\n",[337,1550,1551],{"class":339,"line":718},[337,1552,367],{},[73,1554,1555,1556,1558],{},"Ao usar módulos, você roda ",[334,1557,1252],{}," novamente para baixar o código do\nmódulo local:",[327,1560,1562],{"className":376,"code":1561,"language":378,"meta":332,"style":332},"terraform init  # Detecta e carrega o novo módulo\nterraform plan\nterraform apply\n",[334,1563,1564,1574,1580],{"__ignoreMap":332},[337,1565,1566,1568,1571],{"class":339,"line":340},[337,1567,791],{"class":391},[337,1569,1570],{"class":395}," init",[337,1572,1573],{"class":385},"  # Detecta e carrega o novo módulo\n",[337,1575,1576,1578],{"class":339,"line":346},[337,1577,791],{"class":391},[337,1579,813],{"class":395},[337,1581,1582,1584],{"class":339,"line":352},[337,1583,791],{"class":391},[337,1585,855],{"class":395},[120,1587,1589],{"id":1588},"módulos-públicos-terraform-registry","Módulos públicos (Terraform Registry)",[73,1591,489,1592,1595],{},[81,1593,1594],{},"Terraform Registry"," é como um \"NPM para Terraform\" — um repositório de\nmódulos que a comunidade compartilha. Em vez de criar do zero, você pode usar\nmódulos prontos:",[327,1597,1599],{"className":329,"code":1598,"language":331,"meta":332,"style":332},"# Usa um módulo oficial da AWS para criar um VPC\n# VPC (Virtual Private Cloud) = sua rede privada isolada dentro da AWS\nmodule \"vpc\" {\n  source  = \"terraform-aws-modules\u002Fvpc\u002Faws\"  # Módulo do Registry\n  version = \"5.0.0\"                          # Sempre fixe a versão!\n\n  name = \"meu-vpc\"\n  cidr = \"10.0.0.0\u002F16\"  # Bloco de IPs da rede\n\n  azs             = [\"us-east-1a\", \"us-east-1b\"]  # Zonas de disponibilidade\n  public_subnets  = [\"10.0.1.0\u002F24\", \"10.0.2.0\u002F24\"]\n  private_subnets = [\"10.0.3.0\u002F24\", \"10.0.4.0\u002F24\"]\n\n  enable_nat_gateway = true  # Permite que subnets privadas acessem a internet\n}\n",[334,1600,1601,1606,1611,1616,1621,1626,1630,1635,1640,1644,1649,1654,1659,1663,1668],{"__ignoreMap":332},[337,1602,1603],{"class":339,"line":340},[337,1604,1605],{},"# Usa um módulo oficial da AWS para criar um VPC\n",[337,1607,1608],{"class":339,"line":346},[337,1609,1610],{},"# VPC (Virtual Private Cloud) = sua rede privada isolada dentro da AWS\n",[337,1612,1613],{"class":339,"line":352},[337,1614,1615],{},"module \"vpc\" {\n",[337,1617,1618],{"class":339,"line":358},[337,1619,1620],{},"  source  = \"terraform-aws-modules\u002Fvpc\u002Faws\"  # Módulo do Registry\n",[337,1622,1623],{"class":339,"line":364},[337,1624,1625],{},"  version = \"5.0.0\"                          # Sempre fixe a versão!\n",[337,1627,1628],{"class":339,"line":638},[337,1629,620],{"emptyLinePlaceholder":619},[337,1631,1632],{"class":339,"line":644},[337,1633,1634],{},"  name = \"meu-vpc\"\n",[337,1636,1637],{"class":339,"line":650},[337,1638,1639],{},"  cidr = \"10.0.0.0\u002F16\"  # Bloco de IPs da rede\n",[337,1641,1642],{"class":339,"line":656},[337,1643,620],{"emptyLinePlaceholder":619},[337,1645,1646],{"class":339,"line":662},[337,1647,1648],{},"  azs             = [\"us-east-1a\", \"us-east-1b\"]  # Zonas de disponibilidade\n",[337,1650,1651],{"class":339,"line":668},[337,1652,1653],{},"  public_subnets  = [\"10.0.1.0\u002F24\", \"10.0.2.0\u002F24\"]\n",[337,1655,1656],{"class":339,"line":673},[337,1657,1658],{},"  private_subnets = [\"10.0.3.0\u002F24\", \"10.0.4.0\u002F24\"]\n",[337,1660,1661],{"class":339,"line":678},[337,1662,620],{"emptyLinePlaceholder":619},[337,1664,1665],{"class":339,"line":684},[337,1666,1667],{},"  enable_nat_gateway = true  # Permite que subnets privadas acessem a internet\n",[337,1669,1670],{"class":339,"line":690},[337,1671,367],{},[1238,1673,1674],{},[73,1675,1676,1679],{},[81,1677,1678],{},"Dica",": módulos prontos economizam muito tempo, mas sempre leia o código\nantes de usar. Um módulo mal feito pode criar recursos caros ou inseguros\nque você não esperava.",[11,1681,1683],{"id":1682},"erros-comuns-erros-comuns","Erros comuns {#erros-comuns}",[120,1685,1687,1688,1690],{"id":1686},"_1-commitar-o-arquivo-tfstate-no-git","1. Commitar o arquivo ",[334,1689,496],{}," no Git",[73,1692,1693,1696],{},[81,1694,1695],{},"Problema",": o state contém informações sensíveis (IPs, IDs internos) e é\nbinário. Se duas pessoas editarem ao mesmo tempo, o Git não consegue mesclar —\nvira conflito impossível de resolver.",[73,1698,1699,1702,1703,1706,1707,1710],{},[81,1700,1701],{},"Solução",": adicione ",[334,1704,1705],{},"*.tfstate"," ao ",[334,1708,1709],{},".gitignore"," e use remote state (S3,\nTerraform Cloud, etc).",[120,1712,1714],{"id":1713},"_2-commitar-credenciais-no-código","2. Commitar credenciais no código",[73,1716,1717,1719,1720,590,1723,1726,1727,1730],{},[81,1718,1695],{},": colocar ",[334,1721,1722],{},"access_key",[334,1724,1725],{},"secret_key"," diretamente no ",[334,1728,1729],{},"provider","\n\"faz funcionar\", mas vaza suas chaves da AWS para o mundo (se o repositório for\npúblico).",[73,1732,1733,1735,1736,1739,1740,1743,1744,1747],{},[81,1734,1701],{},": nunca coloque segredos no código. Use variáveis de ambiente, AWS\nCLI (",[334,1737,1738],{},"aws configure","), ou um gerenciador de segredos (AWS Secrets Manager,\nVault). Para senhas de banco, use o resource ",[334,1741,1742],{},"aws_secretsmanager_secret"," e\nreferencie via ",[334,1745,1746],{},"data"," block.",[120,1749,1751],{"id":1750},"_3-não-fixar-versões-de-provider-e-módulos","3. Não fixar versões de provider e módulos",[73,1753,1754,1756,1757,1759,1760,1763],{},[81,1755,1695],{},": sem versão fixada, ",[334,1758,1252],{}," pode baixar uma versão nova\ndo provider com ",[99,1761,1762],{},"breaking changes"," (mudanças que quebram compatibilidade). Seu\ncódigo para de funcionar do nada.",[73,1765,1766,1768],{},[81,1767,1701],{},": sempre fixe versões:",[327,1770,1772],{"className":329,"code":1771,"language":331,"meta":332,"style":332},"# Bom — fixa na major version\nversion = \"~> 5.0\"\n\n# Melhor — fixa exata\nversion = \"5.32.0\"\n\n# Ruim — pega qualquer versão (até betas)\nversion = \">= 0\"\n",[334,1773,1774,1779,1784,1788,1793,1798,1802,1807],{"__ignoreMap":332},[337,1775,1776],{"class":339,"line":340},[337,1777,1778],{},"# Bom — fixa na major version\n",[337,1780,1781],{"class":339,"line":346},[337,1782,1783],{},"version = \"~> 5.0\"\n",[337,1785,1786],{"class":339,"line":352},[337,1787,620],{"emptyLinePlaceholder":619},[337,1789,1790],{"class":339,"line":358},[337,1791,1792],{},"# Melhor — fixa exata\n",[337,1794,1795],{"class":339,"line":364},[337,1796,1797],{},"version = \"5.32.0\"\n",[337,1799,1800],{"class":339,"line":638},[337,1801,620],{"emptyLinePlaceholder":619},[337,1803,1804],{"class":339,"line":644},[337,1805,1806],{},"# Ruim — pega qualquer versão (até betas)\n",[337,1808,1809],{"class":339,"line":650},[337,1810,1811],{},"version = \">= 0\"\n",[120,1813,1815,1816,1818],{"id":1814},"_4-rodar-terraform-apply-sem-revisar-o-plan","4. Rodar ",[334,1817,542],{}," sem revisar o plan",[73,1820,1821,1823,1824,1826],{},[81,1822,1695],{},": em infraestrutura grande, um ",[334,1825,556],{}," cego pode destruir recursos\ncríticos que você não percebeu no plan.",[73,1828,1829,1831],{},[81,1830,1701],{},": sempre leia o plan. Preste atenção especial em:",[284,1833,1834,1842],{},[19,1835,1836,1841],{},[81,1837,1838],{},[334,1839,1840],{},"- destroy",": recursos que serão apagados — é isso que você quer?",[19,1843,1844,1849],{},[81,1845,1846],{},[334,1847,1848],{},"~ in-place",": recursos que serão modificados — pode causar downtime?",[73,1851,1852],{},"Em produção, salve o plan e aplique-o depois:",[327,1854,1856],{"className":376,"code":1855,"language":378,"meta":332,"style":332},"terraform plan -out=plan.tfplan    # Salva o plano\nterraform apply plan.tfplan        # Aplica exatamente o que foi salvo\n",[334,1857,1858,1871],{"__ignoreMap":332},[337,1859,1860,1862,1865,1868],{"class":339,"line":340},[337,1861,791],{"class":391},[337,1863,1864],{"class":395}," plan",[337,1866,1867],{"class":402}," -out=plan.tfplan",[337,1869,1870],{"class":385},"    # Salva o plano\n",[337,1872,1873,1875,1877,1880],{"class":339,"line":346},[337,1874,791],{"class":391},[337,1876,1081],{"class":395},[337,1878,1879],{"class":395}," plan.tfplan",[337,1881,1882],{"class":385},"        # Aplica exatamente o que foi salvo\n",[120,1884,1886],{"id":1885},"_5-um-state-para-tudo","5. Um state para tudo",[73,1888,1889,1891],{},[81,1890,1695],{},": colocar dev, staging e produção no mesmo state. Uma mudança em\ndev pode acidentalmente afetar produção.",[73,1893,1894,549,1896,1899],{},[81,1895,1701],{},[81,1897,1898],{},"um state por ambiente",". Use workspaces ou, melhor ainda,\ndiretórios\u002Fseparação de backend:",[327,1901,1904],{"className":1902,"code":1903,"language":822},[820],"projeto\u002F\n├── environments\u002F\n│   ├── dev\u002F\n│   │   ├── backend.tf    # backend S3 com key=\"dev\u002Fterraform.tfstate\"\n│   │   └── main.tf\n│   └── prod\u002F\n│       ├── backend.tf    # backend S3 com key=\"prod\u002Fterraform.tfstate\"\n│       └── main.tf\n",[334,1905,1903],{"__ignoreMap":332},[73,1907,1908,1909,1912],{},"Assim cada ambiente é totalmente isolado — um ",[334,1910,1911],{},"terraform destroy"," em dev nunca\ntocará produção.",[1914,1915],"hr",{},[73,1917,1918,1921,1922,898],{},[81,1919,1920],{},"Precisa de ajuda com Terraform?"," A Inicialize Tec implementa infraestrutura\ncomo código, migra ambientes manuais para Terraform e estrutura pipelines de\nCI\u002FCD para IaC. ",[22,1923,1925],{"href":1924},"\u002F#top","Conversamos sobre seu caso",[1927,1928,1929],"style",{},"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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":332,"searchDepth":352,"depth":352,"links":1931},[1932,1933,1936,1939,1945,1954,1955,1960,1964],{"id":13,"depth":346,"text":14},{"id":70,"depth":346,"text":71,"children":1934},[1935],{"id":122,"depth":352,"text":123},{"id":192,"depth":346,"text":193,"children":1937},[1938],{"id":319,"depth":352,"text":320},{"id":456,"depth":346,"text":457,"children":1940},[1941,1942,1943,1944],{"id":463,"depth":352,"text":464},{"id":474,"depth":352,"text":475},{"id":485,"depth":352,"text":486},{"id":517,"depth":352,"text":518},{"id":560,"depth":346,"text":561,"children":1946},[1947,1948,1950,1951,1952,1953],{"id":571,"depth":352,"text":572},{"id":600,"depth":352,"text":1949},"Passo 1: criar o arquivo main.tf",{"id":780,"depth":352,"text":781},{"id":800,"depth":352,"text":801},{"id":842,"depth":352,"text":843},{"id":865,"depth":352,"text":866},{"id":890,"depth":346,"text":891},{"id":1127,"depth":346,"text":1128,"children":1956},[1957,1958,1959],{"id":1138,"depth":352,"text":1139},{"id":1165,"depth":352,"text":1166},{"id":1256,"depth":352,"text":1257},{"id":1266,"depth":346,"text":1267,"children":1961},[1962,1963],{"id":1285,"depth":352,"text":1286},{"id":1588,"depth":352,"text":1589},{"id":1682,"depth":346,"text":1683,"children":1965},[1966,1968,1969,1970,1972],{"id":1686,"depth":352,"text":1967},"1. Commitar o arquivo .tfstate no Git",{"id":1713,"depth":352,"text":1714},{"id":1750,"depth":352,"text":1751},{"id":1814,"depth":352,"text":1971},"4. Rodar terraform apply sem revisar o plan",{"id":1885,"depth":352,"text":1886},"infraestrutura","2026-08-26","Guia prático de Terraform para iniciantes: crie, modifique e versione sua infraestrutura na nuvem com código — sem precisar clicar em painéis.","md",[791,105,1978,1979,1980,1981],"infraestrutura como código","AWS","provisionamento","devops",{},"\u002Finfraestrutura\u002Fterraform-infraestrutura-como-codigo",{"title":5,"description":1975},"terraform-infraestrutura-como-codigo","infraestrutura\u002Fterraform-infraestrutura-como-codigo","eX0WCcfSt_j_PuGllWVs4tG_qsY3xcG_k84kJ8-_U-w",1787796309109]