·11 min read

AI Coding Rules for DevOps and IaC

Practical AI coding rules for Terraform, Kubernetes, Docker, and CI/CD pipelines. Stop your AI assistant from generating insecure or brittle infrastructure.

Why DevOps needs AI rules

AI coding assistants are great at writing application code. But hand them a Terraform module or a Kubernetes manifest and things get messy fast. You get resources with no tags, containers running as root, hardcoded secrets in CI pipelines, and Helm charts that would fail any security scan.

The problem is not that the AI is bad at infrastructure. It is that infrastructure code has stricter consequences for mistakes. A bug in a React component shows a broken UI. A bug in a Terraform module can expose a database to the public internet or spin up resources that cost thousands of dollars overnight.

This post covers the specific AI rules you should write for DevOps and Infrastructure as Code workflows. Every section includes concrete rule examples you can drop into your Cursor rules, CLAUDE.md, or Windsurf rules today.

Terraform and OpenTofu rules

Terraform is where most teams start with IaC, and it is where AI assistants make the most expensive mistakes. Here are the rules that matter.

Module structure

## Terraform conventions

- All infrastructure lives in `infra/` at the repo root.
- Each logical grouping is a module in `infra/modules/`.
- Root modules in `infra/environments/` (dev, staging, prod) call shared modules.
- Every module must have: main.tf, variables.tf, outputs.tf, and a README.md.
- Use `terraform fmt` formatting. Do not manually align equals signs.

Without structure rules, the AI creates resources inline in a single main.tf file. That works for a demo. It falls apart at 50 resources.

Naming and tagging

## Resource naming

- All resource names use the pattern: \${var.project}-\${var.environment}-\${purpose}
- Example: myapp-prod-api-gateway, myapp-staging-worker-queue
- Every resource that supports tags must include at minimum:
  - Project: var.project
  - Environment: var.environment
  - ManagedBy: "terraform"
  - Owner: var.team

## Do NOT
- Do not hardcode resource names. Always use variables.
- Do not create resources without tags.
- Do not use the "default" name for any resource.

Tags are how you track costs, enforce policies, and figure out who owns what at 3 AM during an incident. AI assistants almost never add them unless you explicitly require it.

State and backend

## State management

- Remote state only. Never use local state.
- Backend config lives in `infra/environments/\${env}/backend.tf`.
- Use state locking (S3 native locking with use_lockfile = true for AWS, GCS for Google Cloud).
- Never store secrets in Terraform state. Use references to secret managers.
- Do not use terraform_remote_state data sources. Use SSM parameters or outputs files.

Security rules for Terraform

This is the most critical section. AI assistants default to permissive configurations because that is what appears most often in training data (tutorials and blog posts that prioritize getting something working, not security).

## Security - Terraform

- Never use 0.0.0.0/0 in security group ingress rules unless the resource is a public-facing load balancer.
- Never create IAM policies with Action: "*" or Resource: "*".
- Always enable encryption at rest for databases, S3 buckets, and EBS volumes.
- Always enable versioning on S3 buckets.
- Use aws_iam_policy_document data sources instead of inline JSON policies.
- Database instances must not have publicly_accessible = true.
- RDS instances must have deletion_protection = true in production.
- All secrets go in AWS Secrets Manager or HashiCorp Vault, referenced via data sources.

## Patterns to follow

# Good: scoped IAM policy
data "aws_iam_policy_document" "lambda_exec" {
  statement {
    actions   = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
    resources = ["arn:aws:logs:*:\${data.aws_caller_identity.current.account_id}:*"]
  }
}

# Bad: overly permissive
resource "aws_iam_policy" "bad" {
  policy = jsonencode({
    Statement = [{
      Action   = "*"
      Resource = "*"
      Effect   = "Allow"
    }]
  })
}

These rules prevent the most common security mistakes in AI-generated Terraform. For more on structuring rules with examples like these, read the best practices for AI coding rules.

Kubernetes manifest rules

Kubernetes YAML is verbose and error-prone. AI assistants handle the boilerplate well but consistently miss security and operational best practices.

Pod security

## Kubernetes pod security

- All containers must set:
  - resources.requests and resources.limits for cpu and memory
  - securityContext.runAsNonRoot: true
  - securityContext.readOnlyRootFilesystem: true
  - securityContext.allowPrivilegeEscalation: false
- Never use the :latest tag. Always pin image versions with a SHA digest or specific version.
- Always include liveness and readiness probes.
- Never mount the service account token unless the pod needs Kubernetes API access (automountServiceAccountToken: false).

## Example pod security context

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL

Resource organization

## Kubernetes organization

- One resource per YAML file. Do not combine multiple resources with ---.
- File naming: \${resource-type}-\${name}.yaml (e.g., deployment-api.yaml, service-api.yaml).
- Directory structure mirrors namespaces: k8s/\${namespace}/\${app}/.
- Always include namespace in metadata. Never rely on kubectl context.
- Labels must include: app.kubernetes.io/name, app.kubernetes.io/component, app.kubernetes.io/part-of.

Helm chart rules

## Helm conventions

- Values files per environment: values.yaml (defaults), values-staging.yaml, values-prod.yaml.
- Never hardcode values in templates. Everything configurable goes in values.yaml.
- Use named templates (_helpers.tpl) for repeated label blocks and annotations.
- Chart.yaml must specify appVersion matching the deployed container tag.
- Always include NOTES.txt for post-install instructions.

Docker and container rules

Dockerfile generation is one area where AI assistants actually perform well, but they consistently miss optimization and security details.

## Dockerfile conventions

- Always use multi-stage builds for compiled languages (Go, Rust, TypeScript).
- Base images: use specific version tags, never :latest.
  - Node.js: node:22-slim (not node:22 or node:latest)
  - Go: golang:1.24-alpine for build, gcr.io/distroless/static-debian12 for runtime
  - Python: python:3.13-slim
- Final stage must run as non-root user (USER 1001:1001).
- Copy only what is needed. Never COPY . . in the final stage.
- Order layers by change frequency: OS deps -> app deps -> source code.
- Include a .dockerignore that excludes: .git, node_modules, .env*, *.md, tests/.
- HEALTHCHECK must be defined for every production image.
- Do not use ADD unless extracting archives. Use COPY for files.

## Multi-stage example (Node.js)

FROM node:22-slim AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY src/ ./src/
COPY tsconfig.json ./
RUN pnpm build

FROM node:22-slim AS runner
WORKDIR /app
RUN addgroup --gid 1001 appgroup && adduser --uid 1001 --gid 1001 appuser
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER 1001:1001
EXPOSE 3000
HEALTHCHECK CMD ["node", "-e", "fetch('http://localhost:3000/health')"]
CMD ["node", "dist/index.js"]

The multi-stage build rule alone saves significant image size. Without it, AI assistants routinely produce single-stage images that include compilers, dev dependencies, and build artifacts in the final image.

CI/CD pipeline rules

CI/CD pipelines are security-sensitive and hard to debug. Rules here prevent the most painful mistakes.

General pipeline rules

## CI/CD conventions

- Never hardcode secrets in pipeline files. Use the platform's secret management:
  - GitHub Actions: \${{ secrets.MY_SECRET }}
  - GitLab CI: CI/CD variables marked as masked and protected
- Pin all third-party actions and orbs to a full SHA, not a version tag.
  - Good: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
  - Bad: uses: actions/checkout@v4
- Every pipeline must include: lint, test, security scan, build, deploy stages.
- Use environment-specific deployment gates (manual approval for production).
- Cache dependencies between runs (node_modules, .terraform, Go module cache).

GitHub Actions specifics

## GitHub Actions rules

- Workflows live in .github/workflows/ with descriptive names (ci.yml, deploy-prod.yml).
- Use the minimum required permissions. Always set top-level permissions block:
  permissions:
    contents: read
- Use OIDC for cloud provider authentication instead of long-lived credentials.
- Reusable workflows go in .github/workflows/ with the workflow_call trigger.
- Matrix builds for multi-version testing. Do not duplicate jobs.
- Artifact retention: 7 days for CI artifacts, 90 days for release artifacts.

Pinning actions to SHA hashes instead of version tags prevents supply chain attacks. This is one of the most important security practices in CI/CD, and AI assistants almost never do it by default.

Security scanning rules

Infrastructure code should be scanned just like application code. These rules ensure the AI integrates scanning into the workflow rather than treating it as an afterthought.

## Security scanning

- Terraform: Run `tflint` and `trivy config` on every PR. (tfsec has been deprecated and merged into Trivy.)
- Kubernetes: Run `kubeconform` for schema validation and `trivy` for misconfigurations.
- Docker: Run `trivy image` on built images. Fail on HIGH and CRITICAL CVEs.
- Dependencies: Run `trivy fs` or Dependabot for known vulnerabilities.
- Secrets: Run `gitleaks` or `trufflehog` on every commit.

## CI integration pattern (GitHub Actions)

- name: Scan Terraform
  run: trivy config --severity HIGH,CRITICAL --exit-code 1 infra/

- name: Scan container image
  run: trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:\${{ github.sha }}

Including these rules means the AI adds scanning steps when it generates new pipelines or Dockerfiles, instead of just generating the happy path.

Organizing DevOps rules across tools

DevOps rules tend to be long because they cover multiple technologies. The key is splitting them into focused files rather than one giant document.

For Cursor, use separate rule files with targeted globs:

---
description: Terraform conventions and security
globs: ["infra/**/*.tf", "**/*.tfvars"]
alwaysApply: false
---
---
description: Kubernetes manifest conventions
globs: ["k8s/**/*.yaml", "k8s/**/*.yml", "helm/**/*"]
alwaysApply: false
---
---
description: Dockerfile and container conventions
globs: ["**/Dockerfile*", "**/.dockerignore", "**/docker-compose*.yml"]
alwaysApply: false
---
---
description: CI/CD pipeline conventions
globs: [".github/workflows/**", ".gitlab-ci.yml", "Jenkinsfile"]
alwaysApply: false
---

For Claude Code, use the CLAUDE.md hierarchy described in the monorepo rules guide. Place a CLAUDE.md in infra/ for Terraform rules, in k8s/ for Kubernetes rules, and at the root for CI/CD and Docker conventions.

This separation keeps each rules file under 500 lines and ensures the AI only loads relevant rules when working on a specific file type.

Sharing DevOps rules across teams

Infrastructure conventions are some of the most reusable rules you can write. Your Terraform naming standards, Kubernetes security baselines, and CI/CD patterns likely apply across every project in your organization.

With localskills.sh, you can publish each category as a separate skill and install them wherever they are needed:

# Publish your Terraform security baselines
localskills publish --team platform-eng --name terraform-security-rules

# Install in any project
localskills install platform-eng/terraform-security-rules --target cursor claude windsurf

The CLI handles format differences between tools. One published skill installs as Cursor .mdc files, Claude Code CLAUDE.md entries, or Windsurf .md rules depending on the target. Read the publish your first skill guide to get started.

Putting it all together

Here is a complete directory structure for a project with well-organized DevOps AI rules:

my-project/
  CLAUDE.md                           # Root: language, naming, general conventions
  .cursor/rules/
    general.mdc                       # Always active: shared conventions
    terraform.mdc                     # globs: infra/**/*.tf
    kubernetes.mdc                    # globs: k8s/**/*.yaml
    docker.mdc                        # globs: **/Dockerfile*
    ci-cd.mdc                         # globs: .github/workflows/**
  infra/
    CLAUDE.md                         # Terraform-specific rules for Claude Code
    modules/
      networking/
      compute/
      database/
    environments/
      dev/
      staging/
      prod/
  k8s/
    CLAUDE.md                         # Kubernetes-specific rules for Claude Code
    production/
    staging/
  .github/
    workflows/
      ci.yml
      deploy-prod.yml
  Dockerfile
  docker-compose.yml

Each rules file stays focused on one technology. The AI loads only what it needs based on the files you are working with.

Summary

AI coding rules for DevOps and IaC follow the same principles as application code rules: be specific, include examples, and set clear boundaries. The stakes are higher because infrastructure mistakes affect security, costs, and reliability directly.

The rules that matter most:

  1. Terraform: Enforce tagging, naming conventions, remote state, and least-privilege IAM policies
  2. Kubernetes: Require resource limits, non-root containers, pinned image versions, and security contexts
  3. Docker: Mandate multi-stage builds, minimal base images, non-root users, and health checks
  4. CI/CD: Pin action versions to SHA hashes, use OIDC auth, and never hardcode secrets
  5. Security scanning: Integrate tflint, trivy, and gitleaks into every pipeline

For more on writing effective rules, see the best practices guide or browse 20 real-world .cursorrules examples for inspiration.


Ready to share your DevOps rules across your team and every project? Create a free account on localskills.sh and publish your infrastructure rules as reusable skills.

npm install -g @localskills/cli
localskills login
localskills publish