Przejdź do treści
Biblioteka skilli
DevOps i chmura · Budowanie i kod

infrastructure-as-code-terraform

/infrastructure-as-code-terraform

Pisze, organizuje i bezpiecznie stosuje Terraform: projekt modułów, zdalny stan, workspace'y, przegląd planu i import istniejących zasobów.

Licencja
Apache-2.0
Ostatnia zmiana repozytorium
28.07.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 28.07.2026, bez odwołań do wycofanych modeli i API.

Licencja

Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.

Co robi i kiedy

Pisze, organizuje i bezpiecznie stosuje Terraform: projekt modułów, zdalny stan, workspace'y, przegląd planu i import istniejących zasobów.

Wyzwalacze z opisu

write Terraform for X,structure a Terraform repo/modules,manage remote state,import existing infrastructure into Terraform,review a Terraform plan,
Oryginalny opis (EN)

Authors, structures, and safely applies Terraform infrastructure-as-code, including module design, remote state, workspaces, plan review, and importing existing resources. Use when the user asks to "write Terraform for X," "structure a Terraform repo/modules," "manage remote state," "import existing infrastructure into Terraform," "review a Terraform plan," or "safely apply/destroy infrastructure changes.

Jak działa

  1. Purpose
  2. When to use
  3. Prerequisites & environment
  4. Step-by-step guidance
  5. Best practices
  6. Common pitfalls
  7. Worked example
  8. Cross-references
Sekcje z nagłówków SKILL.md, w oryginale · 290 linii, 1 540 słów
Podgląd SKILL.md
---
name: infrastructure-as-code-terraform
description: >
  Authors, structures, and safely applies Terraform infrastructure-as-code,
  including module design, remote state, workspaces, plan review, and
  importing existing resources. Use when the user asks to "write Terraform
  for X," "structure a Terraform repo/modules," "manage remote state,"
  "import existing infrastructure into Terraform," "review a Terraform
  plan," or "safely apply/destroy infrastructure changes."
license: Apache-2.0
compatibility: "Claude Code, GitHub Copilot, OpenAI Codex, Cursor, Gemini CLI"
metadata:
  domain: devops
  maturity: stable
---

# Infrastructure as Code (Terraform)

## Purpose

Terraform lets infrastructure be declared as versioned, reviewable code
rather than configured by hand through cloud consoles, which is what makes
infrastructure changes auditable, repeatable across environments, and safe
to change collaboratively. The operational risk it manages is drift and
irreversibility: a `terraform apply` can create, modify, or destroy real
cloud resources, so the workflow around *how* Terraform is run (plan
review, state locking, blast-radius scoping) matters as much as the HCL
itself.

## When to use

- Provisioning new cloud infrastructure (VPCs, compute, managed databases,
  Kubernetes clusters, IAM) that should be reproducible across
  environments.
- Structuring a Terraform codebase into reusable modules instead of one
  large monolithic configuration.
- Setting up or migrating remote state (e.g., to an S3 + DynamoDB or
  Terraform Cloud/Enterprise backend) with locking.
- Bringing existing, manually-created cloud resources under Terraform
  management (`import`).
- Reviewing a `terraform plan` output before an apply to a shared or
  production environment.
- Safely decommissioning infrastructure (`terraform destroy` or resource
  removal) without unintended blast radius.

## Prerequisites & environment

- Terraform ≥ 1.5 is recommended: it introduced `import` blocks (config-driven
  imports, reviewable in a plan) and `moved`/`check` blocks matured around
  this line; Terraform ≥ 1.7 added `terraform test`. Terraform 0.12–0.14 
  used different HCL2 syntax nuances — confirm the version before assuming
  syntax compatibility, especially for `for_each`/`dynamic` blocks.
- A configured cloud provider credential with least-privilege permissions
  scoped to what the configuration actually manages (not account-owner/
  root credentials).
- A remote backend for state (S3+DynamoDB, Azure Storage, GCS, or
  Terraform Cloud) — local state files are unsafe for anything beyond a
  single-person experiment because they aren't locked or shared.
- `tflint` and/or `terraform validate`, plus a policy tool if enforcing
  guardrails (OPA/Conftest, Sentinel on Terraform Cloud/Enterprise, or
  Checkov) — recommended, not optional, for any team-shared repo.
- Version pinning for both Terraform itself (`required_version`) and every
  provider (`required_providers` with version constraints) to avoid
  unannounced behavior changes on `terraform init`.

## Step-by-step guidance

1. **Pin versions and configure a remote backend first.**
   ```hcl
   terraform {
     required_version = ">= 1.7, < 2.0"
     required_providers {
       aws = {
         source  = "hashicorp/aws"
         version = "~> 5.0"
       }
     }
     backend "s3" {
       bucket         = "example-tfstate-<AWS_ACCOUNT_ID>"
       key            = "payments-api/prod/terraform.tfstate"
       region         = "us-east-1"
       dynamodb_table = "terraform-locks"
       encrypt        = true
     }
   }
   ```
   The DynamoDB table provides state locking so two people/pipelines
   can't `apply` concurrently and corrupt state.

2. **Structure reusable modules** with a clear input/output contract
   rather than copy-pasting resource blocks per environment:
   ```
   modules/
     vpc/
       main.tf
       variables.tf
       outputs.tf
   environments/
     dev/main.tf     # module "vpc" { source = "../../modules/vpc" ... }
     staging/main.tf
     prod/main.tf
   ```
   Each environment directory has its own state file/backend key, keeping
   blast radius scoped — a bad plan in `dev` cannot touch `prod` state.

3. **Always review the plan before applying**, especially to shared
   environments:
   ```bash
   terraform plan -out=tfplan
   terraform show -json tfplan | <policy-checker>   # optional automated gate
   terraform apply tfplan
   ```
   Applying a saved plan file (rather than re-running `apply` bare)
   guarantees what gets applied is exactly what was reviewed — state
   can't have drifted in between in a way that silently changes the
   outcome.

4. **Import existing resources instead of recreating them.** With
   Terraform ≥ 1.5, prefer a declarative `import` block (plannable,
   reviewable, and removable after the import is committed) over the
   imperative `terraform import` CLI command:
   ```hcl
   import {
     to = aws_s3_bucket.logs
     id = "example-logs-bucket"
   }

   resource "aws_s3_bucket" "logs" {
     bucket = "example-logs-bucket"
   }
   ```
   Run `terraform plan` to confirm the generated plan shows the resource
   being *adopted*, not recreated, then `terraform apply`. On Terraform
   < 1.5, use `terraform import aws_s3_bucket.logs example-logs-bucket`
   and hand-write the matching resource block so `plan` shows no diff.

5. **Use `moved` blocks when refactoring**, not delete-and-recreate, to
   avoid Terraform planning a destroy+create for a resource that only
   changed its address in code:
   ```hcl
   moved {
     from = aws_instance.web
     to   = module.web_server.aws_instance.this
   }
   ```

6. **Isolate state per environment/blast-radius**, using either separate
   state files (recommended default) or Terraform workspaces
   (`terraform workspace new staging`) for lighter-weight variants of the
   same config. Workspaces share backend config and code, which is
   convenient but makes it easier to accidentally apply against the wrong
   workspace — separate state files per environment directory are safer
   for anything production-facing.

7. **Never treat `terraform destroy` as a routine command.**
   > **Warning:** `terraform destroy` (or removing a resource block, which
   > plans a destroy) is irreversible for stateful resources (databases,
   > buckets with data, volumes) unless backups/snapshots exist
   > independently. Before running it against anything beyond a scratch/dev
   > environment: confirm via `terraform plan -destroy` exactly what will
   > be removed, confirm backups exist for stateful resources, and prefer
   > `terraform state rm` + manual deletion, or scoping `-target` narrowly,
   > over a blanket destroy when only part of the stack should go away.
   ```bash
   terraform plan -destroy -out=tfplan.destroy   # review first, always
   # terraform apply tfplan.destroy              # only after explicit sign-off
   ```

## Best practices

- Keep provider and Terraform version constraints explicit
  (`~> 5.0`, not unpinned) so `terraform init` doesn't silently pick up a
  new major provider version with breaking changes.
- Run `terraform fmt -check` and `terraform validate` in CI so malformed
  or unformatted HCL never reaches review.
- Use `for_each` over `count` for collections of similar resources when
  membership can change by key (e.g., a map of subnets) — `count`-indexed
  resources shift indices and trigger spurious replace/destroy plans when
  an item is removed from the middle of a list.
- Keep secrets out of `.tf`/`.tfvars` files entirely; source them from the
  provider's native secret manager or environment variables
  (`TF_VAR_db_password`) injected at apply time, and mark corresponding
  variables `sensitive = true` so they're redacted from plan/apply output.
- Store `.tfvars` per environment (`dev.tfvars`, `prod.tfvars`) so the
  same module code is reused with different inputs — this is the
  foundation for a clean
  [environment-promotion-strategy](../environment-promotion-strategy/SKILL.md).
- Run `terraform plan` in CI on every PR touching `.tf` files and post the
  plan output as a PR comment for human review before merge/apply — this
  is the IaC equivalent of a code review gate in
  [ci-cd-pipeline-design](../ci-cd-pipeline-design/SKILL.md).
- Prefer many small, single-purpose state files over one giant state file
  — smaller blast radius, faster plans, and less contention on the state
  lock.

## Common pitfalls

- **Symptom:** `terraform plan` shows a resource being destroyed and
  recreated when only an unrelated attribute changed.
  **Fix:** Check whether the changed attribute forces replacement
  (`terraform plan` marks these with `# forces replacement`); if so,
  confirm that's actually intended (some attributes are immutable
  cloud-side) or restructure to avoid the forced replace, e.g. via
  `lifecycle { create_before_destroy = true }` for zero-downtime swaps.

- **Symptom:** Two people run `apply` around the same time and state gets
  corrupted or one person's changes silently disappear.
  **Fix:** This means state locking isn't in place or isn't being
  respected — configure a locking backend (S3+DynamoDB, GCS with native
  locking, Terraform Cloud) and never run `apply` with
  `-lock=false` outside a documented break-glass procedure.

- **Symptom:** A resource that already exists in the cloud (created by
  hand or by a previous tool) causes `terraform apply` to error with
  "already exists" instead of adopting it.
  **Fix:** Import it first (via an `import` block on Terraform ≥ 1.5, or
  `terraform import` on older versions) so Terraform's state matches
  reality before it tries to manage the resource going forward.

- **Symptom:** `terraform plan` output is hundreds of lines of unrelated
  changes on an otherwise small PR.
  **Fix:** This usually indicates state drift (manual console changes
  since the last apply) or a provider version bump changing a default —
  run `terraform plan` on `main` first to see the baseline drift
  separately from your intended change, and reconcile drift in its own
  PR before layering new changes on top.

- **Symptom:** Someone runs `terraform destroy` against what they thought
  was a dev workspace but it was actually pointed at prod state.
  **Fix:** Use separate state files/backends per environment (not just
  workspaces sharing one backend config) with distinct backend `key`
  values, and require `terraform workspace show`/an explicit
  `-var-file=prod.tfvars` confirmation step in any destroy runbook.

## Worked example

**Scenario:** Add a new S3 bucket for application logs in the `staging`
environment, reusing a shared module, with the plan reviewed in CI before
apply.

`modules/logging-bucket/main.tf`:
```hcl
variable "bucket_name" {
  type = string
}

variable "retention_days" {
  type    = number
  default = 90
}

resource "aws_s3_bucket" "this" {
  bucket = var.bucket_name
}

resource "aws_s3_bucket_lifecycle_configuration" "this" {
  bucket = aws_s3_bucket.this.id
  rule {
    id     = "expire-logs"
    status = "Enabled"
    expiration { days = var.retention_days }
  }
}

output "bucket_arn" { value = aws_s3_bucket.this.arn }
```

`environments/staging/main.tf`:
```hcl
module "app_logs" {
  source         = "../../modules/logging-bucket"
  bucket_name    = "example-app-logs-staging"
  retention_days = 30
}
```

CI workflow step (GitHub Actions):
```yaml
- name: Terraform Plan
  working-directory: environments/staging
  run: |
    terraform init
    terraform plan -no-color -out=tfplan | tee plan_output.txt
- name: Post plan to PR
  uses: actions/github-script@v7
  with:
    script: |
      const fs = require('fs');
      const plan = fs.readFileSync('environments/staging/plan_output.txt', 'utf8');
      github.rest.issues.createComment({
        ...context.repo, issue_number: context.issue.number,
        body: "```\n" + plan.slice(-60000) + "\n```"
      });
```
A reviewer reads the posted plan (confirms it's an additive `+ create`,
no unexpected deletes), approves the PR, and a separate `deploy` job
(gated behind the `staging` environment) runs `terraform apply tfplan`
using the exact plan artifact that was reviewed.

## Cross-references

- [gitops-workflow](../gitops-workflow/SKILL.md)
- [environment-promotion-strategy](../environment-promotion-strategy/SKILL.md)
- [ci-cd-pipeline-design](../ci-cd-pipeline-design/SKILL.md)

Wersje

W bazie nie ma innych skilli o nazwie infrastructure-as-code-terraform.

Migawka bazy z 28.10.2026 · wersja paczki bc3a06437137 (skrót SHA-256 całej paczki)

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100terraform-iac
    Zarządza infrastrukturą chmurową w Terraform i OpenTofu: pisze konfiguracje i moduły, obsługuje stan, import istniejących zasobów, wiele środowisk oraz błędy plan i apply.
  • 100infrastructure-as-code
    Pomaga pisać Terraform dla zasobów chmurowych, konfigurować zdalny stan, układać moduły, zarządzać środowiskami, przeglądać plan przed apply i rozwiązywać drift.
  • 100infrastructure-as-code
    Pomaga pisać Terraform dla zasobów w chmurze, ustawiać zdalny stan, projektować moduły wielokrotnego użytku, prowadzić wiele środowisk oraz przeglądać plan i importować zasoby.
  • 100terraform-expert
    Pisze bezpieczny, modularny Terraform: układ zdalnego stanu, struktura modułów, przegląd planu, przypinanie wersji i ograniczanie zasięgu zmian, na pytania o podział stanu i import infrastruktury.
  • 100terraform
    Zarządza infrastrukturą jako kodem w Terraform lub OpenTofu: projekt modułów, stan, dryf, przegląd planu, sekrety i bezpieczne stosowanie zmian bez niszczenia produkcji.
  • 90terraform-guide
    Prowadzi przez projektowanie modułów Terraform 1.12+, izolację środowisk, remote state, for_each i providery.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.