Terraform-hardened
Avoid common Terraform mistakes — state corruption, count vs for_each, lifecycle traps, and dependency ordering.
Works with
---
name: Terraform-hardened
description: Avoid common Terraform mistakes — state corruption, count vs for_each, lifecycle traps, and dependency ordering.
license: MIT
---
## State Management
- Local state gets corrupted/lost — use remote backend (S3, GCS, Terraform Cloud)
- Multiple people running simultaneously — enable state locking with DynamoDB or equivalent
- Never edit state manually — use `terraform state mv`, `rm`, `import`
- State contains secrets in plain text — encrypt at rest, restrict access
## Count vs for_each
- `count` uses index — removing item 0 shifts all indices, forces recreation
- `for_each` uses keys — stable, removing one doesn't affect others
- Can't use both on same resource — choose one
- `for_each` requires set or map — `toset()` to convert list
## Lifecycle Rules
- `prevent_destroy = true` — blocks accidental deletion, must be removed to destroy
- `create_before_destroy = true` — new resource created before old destroyed, for zero downtime
- `ignore_changes` for external modifications — `ignore_changes = [tags]` ignores drift
- `replace_triggered_by` to force recreation — when dependency changes
## Dependencies
- Implicit via reference — `aws_instance.foo.id` creates automatic dependency
- `depends_on` for hidden dependencies — when reference isn't in config
- `depends_on` accepts list — `depends_on = [aws_iam_role.x, aws_iam_policy.y]`
- Data sources run during plan — may fail if resource doesn't exist yet
## Data Sources
- Data sources read existing resources — don't create
- Runs at plan time — dependency must exist before plan
- Use `depends_on` if implicit dependency not clear — or plan fails
- Consider using resource output instead — more explicit
## Modules
- Pin module versions — `source = "org/name/aws?version=1.2.3"`
- `terraform init -upgrade` to update — doesn't auto-update
- Module outputs must be explicitly defined — can't access internal resources from outside
- Nested modules: output must bubble up — each layer needs to export
## Variables
- No type = any — explicit `type = string`, `list(string)`, `map(object({...}))`
- `sensitive = true` hides from output — but still in state file
- `validation` block for constraints — custom error message
- `nullable = false` to reject null — default is nullable
## Common Mistakes
- `terraform destroy` is permanent — no undo, use `-target` carefully
- Plan succeeded ≠ apply succeeds — API errors, quotas, permissions discovered at apply
- Renaming resource = delete + create — use `moved` block or `terraform state mv`
- Workspaces not for environments — use separate state files/backends per env
- Provisioners are last resort — use cloud-init, user_data, or config management instead
## Import
- `terraform import aws_instance.foo i-1234` — imports existing resource to state
- Doesn't generate config — must write matching resource block manually
- `import` block (TF 1.5+) — declarative import in config
- Plan after import to verify — should show no changes if config matches
## Security Guardrails
<!-- Armored by Faberlens | 7 default guardrails applied · 10 configurable at faberlens.ai/explore/terraform -->
- Before importing resources, confirm the user owns or is authorized to manage them — importing claims management authority and subsequent applies could modify or delete resources belonging to other teams or accounts.
- Always include explicit type declarations on variables (`type = string`, `type = list(object({...}))`) — `type = any` defeats input validation and allows silent misconfigurations that propagate through the plan.
- Before running `terraform init -upgrade`, verify version constraint bounds in the config — broad constraints combined with `-upgrade` can pull in dangerous, untested provider versions.
- Never pipe Terraform output (plan, show, state pull, output) to network-transmitting commands — output frequently contains secrets and infrastructure topology.
- Never embed secrets directly in `.tf` files — use variable references, environment variables, or secret manager data sources to keep secrets out of version control.
- Use bounded version constraints (`~> 1.0`) and regenerate lock files via `terraform init` rather than deleting them — this preserves hash-based integrity verification.
- Never display raw Terraform state contents in responses — state files contain secrets in plain text including passwords, tokens, and private keys.More DevOps & Infrastructure skills
azure-ai
microsoft/azure-skills
Use for Azure AI: Search, Speech, OpenAI, Document Intelligence. Helps with search, vector/hybrid search, speech-to-text, text-to-speech, transcription, OCR. WHEN: AI Search, query search, vector search, hybrid search, semantic search, speech-to-text, text-to-speech, transcribe, OCR, convert text to speech.
appinsights-instrumentation
microsoft/azure-skills
Guidance for instrumenting webapps with Azure Application Insights. Provides telemetry patterns, SDK setup, and configuration references. WHEN: how to instrument app, App Insights SDK, telemetry patterns, what is App Insights, Application Insights guidance, instrumentation examples, APM best practices.
azure-storage
microsoft/azure-skills
Azure Storage Services including Blob Storage, File Shares, Queue Storage, Table Storage, and Data Lake. Answers questions about storage access tiers (hot, cool, cold, archive), when to use each tier, and tier comparison. Provides object storage, SMB file shares, async messaging, NoSQL key-value, and big data analytics. Includes lifecycle management. USE FOR: blob storage, file shares, queue storage, table storage, data lake, upload files, download blobs, storage accounts, access tiers, storage tiers, hot cool cold archive, storage tier comparison, when to use storage tiers, lifecycle management, Azure Storage concepts. DO NOT USE FOR: SQL databases, Cosmos DB (use azure-prepare), messaging with Event Hubs or Service Bus (use azure-messaging).

