Scoras Academy

O que é Terraform e Infraestrutura como Código

Este e-book interativo explora o HashiCorp Terraform, a ferramenta de Infraestrutura como Código (IaC) mais adotada do mercado, com base na documentação oficial v1.14.x. Navegue pelas seções para aprender a linguagem HCL, o workflow, o state, os módulos e as boas práticas — e teste seus conhecimentos no quiz final.

"O Terraform é uma ferramenta de infraestrutura como código que permite definir recursos de nuvem e on-premise em arquivos de configuração legíveis por humanos, que você pode versionar, reutilizar e compartilhar." - Documentação oficial da HashiCorp

Com um workflow consistente, o Terraform provisiona e gerencia toda a sua infraestrutura durante todo o seu ciclo de vida. Ele gerencia tanto componentes de baixo nível — como recursos de computação, armazenamento e rede — quanto componentes de alto nível, como entradas de DNS e recursos de SaaS.

🌐 Como o Terraform funciona?

O Terraform cria e gerencia recursos em plataformas de nuvem e outros serviços por meio de suas APIs. Os providers são plugins que permitem ao Terraform trabalhar com praticamente qualquer plataforma ou serviço que possua uma API acessível.

Terraform Registry: a HashiCorp e a comunidade já escreveram milhares de providers — AWS, Azure, Google Cloud, Kubernetes, Helm, GitHub, Splunk, Datadog e muitos mais — todos disponíveis publicamente no registry.

🧭 Por que Infraestrutura como Código?

Escrever infraestrutura como código significa descrever o estado final desejado em arquivos declarativos, em vez de executar passos manuais em consoles web. O código pode ser versionado em Git, revisado em pull requests e reutilizado entre ambientes.

Declarativo: você não escreve instruções passo a passo. O Terraform constrói um grafo de recursos, resolve as dependências e cria ou modifica em paralelo os recursos que não dependem uns dos outros.

💡 Por que Terraform? Os 5 pilares da documentação

Gerencie qualquer infraestrutura

Providers para praticamente qualquer plataforma; abordagem de infraestrutura imutável que reduz a complexidade de upgrades.

Rastreie sua infraestrutura

O Terraform gera um plano e pede aprovação antes de modificar qualquer coisa, e mantém um state file como fonte da verdade.

Automatize mudanças

Arquivos declarativos descrevem o estado final; o Terraform cuida da lógica e da ordem correta das operações.

Padronize configurações

Módulos encapsulam coleções configuráveis de infraestrutura, economizando tempo e incentivando boas práticas.

Colabore

Como a configuração é código, ela vai para o VCS; o HCP Terraform gerencia o workflow entre equipes com state e segredos seguros.

🎯 Casos de Uso Oficiais

A documentação da HashiCorp lista os cenários mais comuns em que o Terraform se destaca. Clique em cada card para explorar os detalhes.

⚖️ Terraform vs. Outras Abordagens

O Terraform não é mutuamente exclusivo com outras ferramentas — ele pode gerenciar desde uma única aplicação até o datacenter inteiro. Veja como ele se compara às alternativas mais comuns:

Abordagem Foco Diferença-chave do Terraform
Chef, Puppet, etc. Gerenciamento de configuração: instalam e gerenciam software em máquinas que já existem O Terraform foca na abstração de mais alto nível — o provisionamento do datacenter e dos serviços — e pode até acionar essas ferramentas no boot (ex.: via cloud-init)
CloudFormation, Heat, etc. Ferramentas de IaC presas a um único provedor de nuvem O Terraform é agnóstico de nuvem, combina múltiplos providers com uma sintaxe unificada e separa a fase de planejamento (plan) da execução (apply)
Boto, Fog, etc. Bibliotecas imperativas específicas de um único provider O Terraform é declarativo e multi-provider: você descreve o estado final, não os passos para chegar lá
Scripts e soluções caseiras Automação ad hoc mantida pela própria equipe O Terraform oferece state, plano de execução e grafo de dependências prontos, sem custo de manutenção de uma ferramenta interna

O Workflow Central: Write → Plan → Apply

Todo o trabalho com Terraform gira em torno de três etapas: você escreve a configuração, o Terraform planeja as mudanças com base no estado atual e, com a sua aprovação, aplica as operações na ordem correta, respeitando as dependências entre recursos. Este fluxo é um loop: a cada mudança, você recomeça do Write.

👁️ O plano como contrato de revisão

Rodar terraform plan sozinho não altera nada: ele lê o estado atual dos objetos remotos (refresh), compara com a configuração e propõe as ações necessárias. Sem a flag -out, o plano é especulativo — ideal para revisão em pull requests.

$ terraform plan -out=plano.tfplan
# salva o plano em disco para aplicar depois
$ terraform apply plano.tfplan

✋ A confirmação do apply

Quando você roda terraform apply sem argumentos, ele primeiro gera um novo plano e exige aprovação explícita antes de tocar na infraestrutura real:

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

🤝 O workflow em equipe

Com várias pessoas colaborando, cada etapa ganha uma camada de processo: o Write acontece em branches de versionamento, o Plan vira plano especulativo revisado no pull request, e o Apply final é conferido contra o state mais recente após o merge — uma mudança manual feita na infra entre a revisão e o merge pode tornar o plano final diferente do que foi aprovado no PR.

O HCP Terraform automatiza exatamente esses pontos de colaboração — veja a seção HCP Terraform.

A Linguagem HCL

A sintaxe nativa do Terraform é definida pela HCL (HashiCorp Configuration Language), a mesma usada em outros produtos HashiCorp. Ela foi desenhada para ser fácil de ler e escrever por humanos — existe também uma variante JSON (.tf.json), mais adequada para geração programática. Dois construtos sustentam tudo: argumentos e blocos.

🧱 Blocos e Labels

Um bloco é um contêiner de conteúdo com um tipo e zero ou mais labels. O bloco resource exige dois labels: o tipo do recurso (definido pelo provider) e um nome local arbitrário que você escolhe.

resource "aws_instance" "web" {
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"

  network_interface {
    # ...
  }
}

O corpo do bloco é delimitado por { e }, e pode aninhar outros blocos e argumentos. A maioria dos recursos do Terraform (resources, data sources, variables, outputs etc.) é implementada como blocos de nível superior.

🟰 Argumentos e Expressões

Um argumento atribui um valor a um nome. O contexto define os tipos válidos, e a maioria dos argumentos aceita expressões — valores literais, referências a outros recursos, chamadas de função e operações.

image_id = "abc123"
subnet_id = aws_subnet.main.id
name     = "${var.environment}-web-server"
enabled  = length(var.subnet_ids) > 0

Identificadores aceitam letras, dígitos, _ e -, mas nunca começam com dígito.

🔤 Tipos de Valores

Primitivos: string, number, bool
Coleções: list(...), set(...), map(...)
Estruturais: object({...}), tuple([...])
null: ausência/omissão de valor
variable "subnet_ids" {
  type = list(string)
}

variable "tags" {
  type = map(string)
}

💬 Comentários e Arquivos

HCL suporta três formas de comentário. O estilo # é o padrão idiomático — ferramentas de formatação automática podem converter // em #.

# Comentário de linha (estilo padrão)
// Também comentário de linha
/* Comentário
   de múltiplas linhas */

O código Terraform vive em arquivos texto .tf com codificação UTF-8. Um módulo é a coleção de arquivos .tf de um diretório: o Terraform avalia todos eles como se fossem um único documento — separar em vários arquivos é pura conveniência de leitura.

Providers

Providers são os plugins que permitem ao Terraform interagir com serviços, provedores de nuvem e outras APIs. Cada configuração deve declarar de quais providers ela precisa, para que o Terraform possa instalá-los e usá-los.

📜 Declarando providers exigidos

Declare o provider no bloco required_providers, dentro do bloco terraform: a chave é o nome local, e o valor traz o source (endereço global) e a restrição de version.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

O endereço de origem segue o formato [<HOSTNAME>/]<NAMESPACE>/<TYPE>; sem hostname, assume-se registry.terraform.io. Rode terraform init para instalar o provider.

🔢 Restrições de versão

Cada provider evolui independentemente; por isso a documentação recomenda fortemente declarar uma restrição de versão para cada um deles.

Sintaxe Significado
= 5.0.0Exatamente a versão 5.0.0
>= 5.0Versão mínima (boa para módulos reutilizáveis)
~> 5.0.4Só patch: >= 5.0.4, < 5.1.0
~> 5.0Minor e patch: >= 5.0, < 6.0

O operador ~> permite incrementar apenas o componente mais à direita da versão. O módulo raiz deve limitar a versão máxima para evitar upgrades acidentais.

👥 Múltiplas configurações do mesmo provider (alias)

É comum precisar do mesmo provider com configurações diferentes — por exemplo, duas regiões da AWS. Use alias para nomear configurações alternativas e o meta-argument provider para escolher qual delas cada recurso ou data source deve usar.

provider "aws" {
  region = "us-east-1"
}

provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

resource "aws_instance" "web" {
  provider = aws.west
  # ...
}

Sem o meta-argument provider, o Terraform deduz a configuração pela primeira palavra do tipo do recurso (ex.: aws_instance → provider aws).

Resources e Data Sources

Um resource é qualquer objeto de infraestrutura que você quer criar e gerenciar com o Terraform — redes virtuais, instâncias de computação ou componentes de mais alto nível, como registros DNS. Já os data sources permitem consultar dados existentes sem criar nem modificar nada.

🏗️ Sintaxe do bloco resource

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type

  tags = {
    Name = "web-server"
  }
}

O endereço deste recurso na configuração é aws_instance.web. Os argumentos específicos (como ami) são definidos pelo schema do provider; os meta-arguments (count, for_each, depends_on, lifecycle, provider) são definidos pelo próprio Terraform.

♻️ O ciclo de vida no apply

Ao aplicar uma configuração, o Terraform executa estas operações:

Cria os recursos da configuração que ainda não existem como objetos reais.
Destrói os recursos que estão no state, mas não existem mais na configuração.
Atualiza in-place os recursos cujos argumentos mudaram.
Destrói e recria os recursos cuja mudança não pode ser feita in-place por limitações da API remota.
Atualiza o state para que configuração, infraestrutura real e state fiquem sincronizados.

🔎 Data sources: consulta sem efeito colateral

Muitos providers oferecem data sources que buscam dados da plataforma — AMIs, zonas, VPCs existentes — para deixar sua configuração mais flexível. O bloco data tem dois labels (tipo e nome), e os dados são referenciados com a sintaxe data.<TYPE>.<NAME>.<ATTRIBUTE>:

data "aws_ami" "web" {
  most_recent = true
  owners      = ["self"]

  tags = {
    Name   = "app-server"
    Tested = "true"
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.web.id
  instance_type = "t3.micro"
}
Leitura no plan: por padrão, o Terraform tenta ler os data sources durante a fase de planejamento (refresh), para que os valores reais apareçam no diff.
Leitura adiada ao apply: quando um argumento do data source depende de um valor que só será conhecido após o apply (atributo computado de outro recurso), a leitura é adiada e os atributos aparecem como (known after apply) no plano.

Variables, Outputs e Locals

Estes três blocos formam a "interface" de um módulo Terraform: as variables são os parâmetros de entrada, os outputs são os valores expostos na saída, e os locals nomeiam expressões reutilizáveis dentro do próprio módulo. Navegue pelas abas para explorar cada um.

State: A Fonte da Verdade

O state é um requisito indispensável para o funcionamento do Terraform. Ele é o banco de dados que conecta a sua configuração ao mundo real: graças a ele, o Terraform sabe que o bloco resource "aws_instance" "foo" representa a instância i-abcd1234 em um sistema remoto.

🗺️ Mapeamento

Liga cada recurso da configuração a um objeto real. Nem todo recurso/provider suporta tags — por isso o Terraform mantém sua própria estrutura de state. Cada objeto remoto deve estar ligado a apenas um recurso.

🧾 Metadados

Guarda as dependências mais recentes de cada recurso — essenciais para destruir na ordem correta recursos que já foram removidos da configuração — e o provider configuration usado com cada recurso.

⚡ Performance

Funciona como cache dos atributos dos recursos. Em infraestruturas grandes, consultar tudo a cada plan seria lento demais (limites de API); flags como -refresh=false usam o cache como referência.

🔄 Sincronização

Por padrão o state fica em um arquivo local. Em equipe, todos precisam trabalhar sobre o mesmo state — a solução recomendada é o state remoto com locking.

🏪 Backends: onde o state mora

Backends determinam onde o state é armazenado e oferecem uma API para state locking. O backend padrão é o local, que grava um arquivo JSON no disco; backends remotos como s3 e remote (HCP Terraform) guardam o state fora da máquina.

terraform {
  backend "s3" {
    bucket = "meu-state-bucket"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

Com backend não-local, o Terraform não persiste o state em disco — grande benefício quando há valores sensíveis no state. Todos os comandos (terraform state, console, taint…) continuam funcionando como se o state fosse local.

🔒 Locking e dados sensíveis

Se o backend suportar, o Terraform trava o state automaticamente em todas as operações que podem escrevê-lo, impedindo que duas pessoas escrevam ao mesmo tempo e corrompam o arquivo. Se o desbloqueio automático falhar, existe o comando terraform force-unlock <LOCK_ID> — use com muito cuidado e apenas para o seu próprio lock.

⚠️ Atenção: o state pode conter valores sensíveis em texto claro (senhas de banco, chaves de API), mesmo quando marcados como sensitive na configuração. Por isso: nunca commite o state no Git e prefira backends remotos com criptografia e controle de acesso.
Nunca edite o state manualmente. Para alterações, use os comandos terraform state, que registram backups e preservam a integridade.

🛠️ Comandos terraform state

Comando O que faz
state listLista os endereços de todos os recursos no state
state showMostra os atributos de um recurso específico
state mvMove/renomeia endereços no state (refatoração sem destruir nada)
state rmRemove um recurso do state sem destruir o objeto real
state pullBaixa o state remoto e o imprime na saída padrão
state pushSobrescreve o state remoto — extremamente perigoso, evite

Todo subcomando que modifica o state grava um arquivo de backup obrigatório antes da alteração.

📥 Import: adotando infra existente

O Terraform consegue importar infraestrutura já existente — criada por outros meios — para passar a gerenciá-la. Ao importar, garanta que cada objeto remoto seja vinculado a apenas uma instância de recurso na configuração.

$ terraform import aws_instance.web i-abcd1234

Também existe o bloco import (plano-driven) e a geração automática de configuração a partir de objetos importados — consulte a documentação de Import para os detalhes.

Módulos

Um módulo é uma coleção de recursos que o Terraform gerencia em conjunto. Modularizar ajuda a padronizar o provisionamento e a reutilizar boas práticas: em vez de repetir a mesma combinação de recursos, você a encapsula uma única vez.

🌳 Raiz e filhos

Todo workspace tem um módulo raiz (os arquivos do diretório de trabalho). Os módulos chamados via blocos module são os módulos filhos — e um filho pode chamar seus próprios módulos aninhados.

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "minha-vpc"
  cidr = "10.0.0.0/16"
}

O terraform init baixa o código do módulo para o disco local (diretório .terraform) durante a etapa de instalação.

📍 Fontes de módulos (source)

Caminhos locais: ./consul ou ../modulos/rede — ideais para fatorar código dentro do mesmo repositório.
Terraform Registry: <NAMESPACE>/<NAME>/<PROVIDER> — a forma nativa de distribuição, com versionamento completo.
Git/GitHub/Bitbucket: repositórios de controle de versão.
Outros: URLs HTTP, buckets S3 e GCS.

🏛️ O Registry público e o versionamento

O Terraform Registry público hospeda uma ampla coleção de módulos mantidos pela HashiCorp, por parceiros e pela comunidade — gratuitos e baixados automaticamente quando você declara source e version no bloco module.

Módulos de registry suportam versionamento: fixe uma versão exata ou use restrições flexíveis. Organizações podem publicar módulos internos no registry privado do HCP Terraform/Terraform Enterprise.

Fluxo de adoção de módulos

1. Develop: desenvolvedores agrupam recursos em um módulo com estrutura padrão e documentação
2. Distribute: publicação no registry público, privado ou em outro source (Git, S3…)
3. Provision: consumidores chamam o módulo com o bloco module e rodam terraform init

Meta-arguments e Expressões

Os meta-arguments são argumentos definidos pelo próprio Terraform (e não pelo provider) que controlam como os recursos são criados e gerenciados. Junto com as funções embutidas e as expressões, eles dão dinamismo à linguagem.

🔢 count

Aceita um número inteiro e cria aquela quantidade de instâncias. Cada instância é identificada por count.index, que começa em 0. O valor precisa ser conhecido antes de qualquer operação remota.

resource "aws_instance" "server" {
  count = 4 # cria quatro instâncias EC2 semelhantes

  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"

  tags = {
    Name = "Server ${count.index}"
  }
}

As instâncias são referenciadas como aws_instance.server[0], [1]… Dica: count = var.habilitar ? 1 : 0 é o padrão clássico de recurso condicional.

🗂️ for_each

Aceita um map ou um set de strings e cria uma instância por elemento, identificada por each.key e each.value. Listas precisam ser convertidas com toset().

resource "azurerm_resource_group" "rg" {
  for_each = tomap({
    a_group       = "eastus"
    another_group = "westus2"
  })
  name     = each.key
  location = each.value
}
count × for_each: use count para instâncias quase idênticas; use for_each quando cada instância precisa de valores distintos. Os dois não podem ser usados juntos no mesmo bloco.

🔗 depends_on

Serve para dependências ocultas: quando um recurso depende do comportamento de outro, mas não usa nenhum dado dele em seus argumentos (ex.: uma instância que precisa de uma policy de IAM aplicada antes do boot).

resource "aws_instance" "example" {
  iam_instance_profile = aws_iam_instance_profile.example

  # Dependência que o Terraform não consegue inferir:
  depends_on = [
    aws_iam_role_policy.example
  ]
}

Use como último recurso: ele torna os planos mais conservadores (mais valores "known after apply"). Prefira referências em expressões, que criam dependências implícitas mais precisas.

🧬 lifecycle

create_before_destroy

Na substituição de um recurso, cria o novo objeto antes de destruir o antigo (o padrão é destruir primeiro). Útil para reduzir indisponibilidade — verifique restrições como nomes únicos.

prevent_destroy

Faz o Terraform rejeitar com erro qualquer plano que destruiria o objeto. Não protege se você remover a configuração do recurso — use com parcimônia.

ignore_changes

Lista de atributos (ou all) que o Terraform ignora ao planejar atualizações — útil quando outro processo gerencia aqueles campos (ex.: tags).

replace_triggered_by / precondition / postcondition

Substitui o recurso quando referências mudam; e validações customizadas avaliadas antes/depois das operações, com condition e error_message.

🧮 Funções embutidas e expressões

Funções úteis

lookup(map, key, default), merge(map1, map2), length(list), toset(), jsonencode(), file(), cidrsubnet()… O Terraform não permite funções definidas pelo usuário.

Expressão for

[for s in var.names : upper(s)] transforma coleções; {for k, v in var.map : k => v} gera maps.

Condicional

condicao ? valor_se_true : valor_se_false — ex.: var.env == "prod" ? "t3.large" : "t3.micro".

locals {
  subnet_count = length(var.subnet_ids)
  all_tags     = merge(var.tags, { ManagedBy = "terraform" })
  first_subnet = lookup(var.subnet_map, "primary", var.subnet_ids[0])
  upper_names  = [for n in var.names : upper(n)]
}

CLI Essencial

O Terraform Community Edition é uma ferramenta gratuita de linha de comando. Estes são os comandos que você usará todos os dias — e dois arquivos/variáveis de ambiente que todo mundo deveria conhecer.

📋 Tabela de comandos

Comando Função
terraform initInicializa o diretório: instala providers e módulos, configura o backend e atualiza o lock file
terraform validateVerifica se a configuração é sintaticamente válida e internamente consistente
terraform fmtReescreve os arquivos no estilo canônico de formatação (indentação, alinhamento)
terraform planCria o plano de execução: refresh do state + comparação + proposta de ações (não aplica nada)
terraform applyExecuta as ações do plano após aprovação (ou aplica um plano salvo com -out)
terraform destroyDestrói todos os objetos remotos gerenciados pela configuração atual
terraform outputLê os outputs do módulo raiz a partir do state (-json/-raw revelam valores sensitive)
terraform showInspeciona o state ou um arquivo de plano em formato legível (ou JSON)
terraform stateGerenciamento avançado do state: list, show, mv, rm, pull, push, replace-provider
terraform workspaceGerencia workspaces: list, new, select, delete, show
terraform importTraz infraestrutura existente para o gerenciamento do Terraform
terraform taintMarca um objeto para substituição (deprecado em favor de -replace no plan/apply)
terraform consoleConsole interativo para experimentar expressões e funções
terraform providersMostra os providers exigidos pela configuração
terraform versionExibe a versão do Terraform e dos providers instalados

🔐 O arquivo .terraform.lock.hcl

O dependency lock file registra as versões exatas de provider que o Terraform selecionou, para que as mesmas decisões sejam repetidas no futuro. Ele é criado e atualizado automaticamente a cada terraform init.

✅ Commite no VCS: a recomendação oficial é versionar o .terraform.lock.hcl junto com a configuração — assim mudanças de dependências passam por code review como qualquer outra mudança. HCP Terraform, CLI e Enterprise obedecem ao lock file ao instalar providers.

🌡️ Variáveis de ambiente úteis

# Logs detalhados no stderr para depuração
export TF_LOG=trace
# Desabilitar logs
export TF_LOG=off
# Persistir o log em arquivo (exige TF_LOG definido)
export TF_LOG_PATH=./terraform.log
# Atribuir valores a input variables
export TF_VAR_region=us-west-1

O formato TF_VAR_<nome> define valores de variáveis e é a última fonte consultada na ordem de precedência — útil em pipelines de CI/CD.

Workspaces

No Terraform CLI, workspaces são instâncias separadas de state dentro do mesmo diretório de trabalho. Como o state é o que associa recursos a objetos reais, rodar a mesma configuração com states diferentes permite gerenciar múltiplos conjuntos de recursos que não se sobrepõem.

🧭 Como funcionam

Todo diretório inicializado começa com um workspace chamado default. Apenas um workspace está selecionado por vez, e a maioria dos comandos interage somente com ele. Com state local, os states ficam no diretório terraform.tfstate.d.

$ terraform workspace list
$ terraform workspace new staging
$ terraform workspace select staging
$ terraform workspace show
$ terraform workspace delete staging

🎯 Quando usar (e quando não usar)

✅ Bom uso: criar uma cópia paralela e descartável da infraestrutura para testar mudanças antes de tocar em produção — muitas vezes associada a uma feature branch, destruída após o merge.
⚠️ Mau uso: decompor sistemas grandes ou separar ambientes que exigem credenciais e controles de acesso diferentes. Workspaces do CLI dividem o mesmo backend — nesses casos, prefira configurações separadas (módulos reutilizáveis + backends distintos).
Não confunda: os workspaces do HCP Terraform são outra coisa — cada um funciona como um diretório de trabalho separado, com configuração, variáveis, state, histórico de runs e permissões próprios.

HCP Terraform

O HCP Terraform (antigo Terraform Cloud) é a aplicação SaaS da HashiCorp que executa o Terraform em um ambiente remoto estável e armazena state e segredos com segurança. Ele existe para potencializar exatamente o workflow central em equipes e organizações.

🖥️ Runs remotos e CLI

Execute a partir do CLI local (com a integração cloud), em ambiente remoto, por triggers do VCS ou via API — o output do plan remoto aparece direto no seu terminal.

🔀 Integração com VCS

Conecta-se a GitHub, GitLab e Bitbucket: ao ligar um workspace a um repositório, novos commits e pull requests disparam planos especulativos automaticamente, com status no próprio PR.

🗄️ State gerenciado

State remoto versionado, criptografado em repouso e com histórico — além de RBAC, single sign-on, registry privado de módulos/providers e políticas Sentinel (policy as code).

🧩 Conectando o CLI ao HCP Terraform

terraform {
  cloud {
    organization = "minha-org"
    hostname     = "app.terraform.io" # opcional; este é o padrão

    workspaces {
      tags = {
        layer  = "networking"
        source = "cli"
      }
    }
  }
}

Com a integração configurada, basta uma API key para editar a configuração e rodar planos especulativos contra a versão mais recente do state, usando as variáveis armazenadas remotamente.

🏷️ As três edições do Terraform

Community Edition

Ferramenta gratuita de linha de comando. Provisiona em qualquer nuvem e gerencia configuração, plugins, infraestrutura e state.

HCP Terraform

SaaS que roda o Terraform em ambiente remoto estável, com state e segredos seguros, RBAC, registry privado e integração com VCS. Muitos recursos são gratuitos para pequenas equipes; planos pagos agregam governança.

Terraform Enterprise

Distribuição self-hosted do HCP Terraform, com limites de recursos customizáveis, suporte dedicado e instalações air-gapped para requisitos rígidos de segurança e conformidade.

Boas Práticas

Recomendações do guia de estilo oficial e da documentação para manter seus projetos Terraform legíveis, seguros e colaborativos.

🗂️ Estrutura de arquivos recomendada

backend.tf    # configuração do backend
main.tf       # blocos resource e data
outputs.tf    # outputs em ordem alfabética
providers.tf  # blocos provider
terraform.tf  # required_version e required_providers
variables.tf  # variables em ordem alfabética
locals.tf     # valores locais

Rode terraform fmt e terraform validate sempre (idealmente no CI) para manter estilo e consistência.

🙈 O que NÃO commitar (.gitignore)

terraform.tfstate e backups terraform.tfstate.*
.terraform.tfstate.lock.info (informações do lock)
O diretório .terraform (providers e módulos baixados)
Arquivos de plano salvos com plan -out
Arquivos .tfvars com informações sensíveis
✅ E o que DEVE ir para o VCS: todos os arquivos .tf, o .terraform.lock.hcl, um .gitignore e um README.md descrevendo código, variáveis e outputs.

🛡️ Segurança no dia a dia

Marque dados sensíveis

Use sensitive = true em variables e outputs para ocultar valores da CLI — lembrando que eles ainda ficam no state; considere valores ephemeral para omiti-los de state e planos.

Menor privilégio

As credenciais usadas pelos providers devem ter apenas as permissões necessárias para os recursos gerenciados — nunca credenciais de administrador "por garantia".

Fixe versões

Declare restrições de versão para todos os providers (required_providers) e para módulos de registry (version), e commite o lock file.

State remoto com locking

Em equipe, use um backend remoto com locking e criptografia em vez do state local — e nunca edite o state na mão: use os comandos terraform state.

Quiz Final: Teste Seus Conhecimentos

Avalie seu aprendizado sobre Terraform com este quiz de 50 perguntas em ordem aleatória. São 45 segundos por questão e a aprovação exige pelo menos 80% de acertos. Você pode refazer quantas vezes quiser — a cada tentativa, perguntas e alternativas mudam de ordem. Boa sorte! 🚀

Próximos Passos na Sua Jornada Terraform

Você percorreu os fundamentos da documentação oficial: o que é IaC, o workflow Write → Plan → Apply, a linguagem HCL, providers, resources, state, módulos, meta-arguments, a CLI, workspaces e o HCP Terraform. A melhor forma de consolidar tudo isso é colocando a mão na massa.

🚀 Continue Praticando

Tutoriais Get Started

A HashiCorp mantém trilhas práticas para provisionar infraestrutura real na AWS, Azure, Google Cloud, OCI e Docker — o melhor próximo passo após este e-book.

Explore o Registry

Navegue pelo Terraform Registry, leia a documentação dos providers que você usa e experimente módulos verificados da comunidade em projetos de estudo.

🧭 Aprofunde os Temas

Releia as seções de State e Meta-arguments — são os temas que mais geram dúvidas na prática — e refaça o Quiz Final até dominar as 50 questões.

💡 Lembre-se das promessas de compatibilidade v1.x: módulos escritos para o Terraform v1.0 continuam rodando plan e apply, sem mudanças obrigatórias, em todos os releases v1.x.

🎓 Sobre a Scoras Academy

Este e-book foi criado pela Scoras Academy, o braço educacional da Scoras Digital. Nossa missão é construir o futuro da IA no Brasil de forma segura, responsável e com excelência técnica.

🏭 Scoras Digital

A primeira fábrica de agentes de IA do Brasil, com 4 anos de experiência construindo soluções personalizadas para empresas nacionais e internacionais.

scoras.com.br

🎓 Scoras Academy

Mais de 1000 alunos formados em cursos práticos de engenharia de IA, desde Python para iniciantes até LangGraph avançado.

scorasacademy.com.br