AI

Set Up Claude Code for DevOps Engineers

Most AI coding tools generate snippets you paste into an editor. Claude Code operates at a different level. It runs real commands on your machine, SSHes into servers, executes Terraform plans, runs Ansible playbooks, and builds Docker images. It inherits your SSH keys, cloud credentials, and kubeconfig. For DevOps engineers, this turns “write me a playbook” into “write it, run it, show me the output” in a single conversation.

Original content from computingforgeeks.com - post 164869

Below are six demos you can reproduce on your own servers, plus the CLAUDE.md rules, permission lockdowns, and hooks that keep Claude Code from wrecking production. Each prompt is copy-pasteable. For the full command reference, see the Claude Code cheat sheet.

Tested March 2026 | Claude Code with Opus 4.6 (80.9% SWE-bench), macOS, Rocky Linux 10 VMs

Prerequisites

  • A Claude subscription (Pro at $20/mo for light use, Max at $100-200/mo for heavy infrastructure sessions) or an Anthropic Console API key
  • macOS, Linux, or Windows with WSL
  • SSH access to at least one Linux server (for demos 1, 2, and 4)
  • Docker installed locally (for demo 3)
  • kubectl with a cluster or minikube (for demo 5, optional)

Opus 4.6 handles complex tasks well: multi-file Terraform refactoring, debugging subtle Ansible failures, designing Kubernetes architectures. Sonnet 4.6 is roughly 5x cheaper and covers routine work: boilerplate generation, Dockerfiles, health checks. Use Sonnet daily, switch to Opus for deep reasoning. The /model command switches mid-session.

Install Claude Code

Claude Code runs on macOS, Linux, and Windows. The native installer is the fastest method:

curl -fsSL https://claude.ai/install.sh | bash

On macOS, Homebrew also works:

brew install --cask claude-code

After installation, navigate to any project directory and run claude to start a session. You’ll be prompted to log in on first launch.

How Claude Code Works for Infrastructure

Claude Code executes bash commands as your user. Whatever you can do in a terminal, Claude Code can do. It picks up your SSH agent, AWS credentials, kubeconfig, Docker socket, and any environment variables in your shell. This makes it immediately useful for infrastructure work without extra configuration.

DevOps TaskWorks?HowWatch Out For
SSH to serversYesssh user@host "cmd" via BashNon-interactive only (no vi/nano)
TerraformYesRuns CLI directly, inherits cloud credsCan run apply/destroy if allowed
AnsibleYesRuns ansible-playbook directlyUse vault password files, not prompts
DockerYesUses your local Docker socketNeeds sandbox exclusion
kubectl / HelmYesReads your ~/.kube/configNeeds ~/.kube access in sandbox
Cloud CLIs (aws, gcloud, az)YesInherits your authenticated sessionWhatever you can do, Claude can do
CI/CD headless modeYesclaude -p "task" --allowedToolsNeeds ANTHROPIC_API_KEY

The 1M token context window (Opus 4.6) means Claude Code can ingest entire infrastructure repositories, including Terraform modules, Ansible roles, and Kubernetes manifests, in a single session without losing context halfway through a refactor.

Demo 1: Server Health Check via SSH

The most relatable demo for any sysadmin. Point Claude Code at a server and ask for a health report. One prompt, multiple SSH commands, formatted results.

Open Claude Code and type this prompt:

SSH into 192.168.1.50 and give me a full health report: OS version,
uptime, disk usage, memory, top 5 CPU processes, any failed systemd
services, and pending security updates

Claude Code connects over SSH and runs the relevant commands on its own: hostnamectl for the OS, uptime, df -h for disk, free -h for memory, ps aux --sort=-%cpu for top processes, systemctl --failed for broken services, and dnf check-update --security for pending patches. The output comes back as a structured report:

Server Health Report: 192.168.1.50
═══════════════════════════════════
OS:        Rocky Linux 10.1 (Blue Onyx)
Kernel:    6.12.8-1.el10.x86_64
Uptime:    14 days, 3:22

Disk Usage:
  /        42% of 50G
  /var     67% of 100G  ⚠ approaching 80%
  /tmp     12% of 10G

Memory:    3.2G used / 8.0G total (40%)
Swap:      0B used / 2.0G total

Top 5 CPU Processes:
  PID   %CPU  COMMAND
  1842  12.3  prometheus
  2104   8.1  grafana-server
  1567   4.2  node_exporter
  1233   2.1  nginx
  1001   0.8  sshd

Failed Services: none

Pending Security Updates: 3 packages
  kernel-6.12.8-1.el10
  openssl-3.2.3-2.el10
  systemd-256.10-1.el10

This replaces the ad-hoc shell script you’d normally write. Claude Code notices that /var is at 67% and flags it proactively, something a raw df -h won’t do for you. You can follow up with “clean old logs on that server” and Claude Code handles it without you writing another command. For a deeper reference on SSH operations, see the SSH commands cheat sheet.

Demo 2: Generate and Run an Ansible Playbook

Ansible playbooks are structured YAML with predictable patterns, which makes them an excellent target for AI generation. The difference with Claude Code is that it doesn’t just write the playbook. It runs it.

Prompt Claude Code with a specific deployment request:

Write an Ansible playbook that installs Nginx on the Rocky Linux 10
server at 192.168.1.50, creates a custom index page, opens firewall
ports 80 and 443, and enables the service. Dry-run first, then apply.

Claude Code generates the playbook with proper module usage:

---
- name: Deploy Nginx on Rocky Linux 10
  hosts: all
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.dnf:
        name: nginx
        state: present

    - name: Deploy custom index page
      ansible.builtin.copy:
        dest: /usr/share/nginx/html/index.html
        content: |
          
          

Deployed by Ansible via Claude Code

owner: nginx group: nginx mode: '0644' - name: Start and enable nginx ansible.builtin.systemd: name: nginx state: started enabled: true - name: Open HTTP and HTTPS in firewalld ansible.posix.firewalld: service: "{{ item }}" permanent: true immediate: true state: enabled loop: - http - https

It runs the dry run (--check) first to show what would change:

PLAY [Deploy Nginx on Rocky Linux 10] *****************************************

TASK [Install nginx] **********************************************************
changed: [192.168.1.50]

TASK [Deploy custom index page] ***********************************************
changed: [192.168.1.50]

TASK [Start and enable nginx] *************************************************
changed: [192.168.1.50]

TASK [Open HTTP and HTTPS in firewalld] ***************************************
changed: [192.168.1.50] => (item=http)
changed: [192.168.1.50] => (item=https)

PLAY RECAP ********************************************************************
192.168.1.50    : ok=4    changed=4    unreachable=0    failed=0

After confirming the dry run looks correct, Claude Code runs the playbook for real and verifies with curl http://192.168.1.50 to confirm Nginx responds. The entire loop happens in one conversation. If you need Ansible installed on your control machine, handle that first.

Demo 3: Build a Production Dockerfile

Claude Code doesn’t just generate Dockerfiles. It writes the file, builds the image, and reports the result.

Create a multi-stage Dockerfile for the Python Flask app in ./app/.
Alpine base, non-root user, proper layer caching. Build it and compare
the size against a naive single-stage build.

Claude Code generates a production-quality Dockerfile:

# Build stage
FROM python:3.12-alpine AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# Runtime stage
FROM python:3.12-alpine
RUN adduser -D appuser
WORKDIR /app
COPY --from=builder /install /usr/local
COPY ./app/ .
USER appuser
EXPOSE 5000
CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]

It builds both versions and shows the size comparison:

REPOSITORY    TAG            SIZE
myapp         multi-stage    87MB
myapp         naive          1.2GB

The multi-stage build is 93% smaller. Security best practices are applied by default: non-root user, no cache directories in the image, minimal base. If you’re running Docker on RHEL systems, the Docker Engine installation guide for Rocky Linux 10 covers the prerequisites.

Demo 4: Diagnose and Fix a Broken Service

This is the demo that sells Claude Code to sysadmins. Break something on purpose, then watch Claude Code trace the problem and fix it without hand-holding.

Introduce a syntax error in the Nginx config:

ssh [email protected] "sed -i 's/;$//' /etc/nginx/nginx.conf"
ssh [email protected] "systemctl restart nginx"

Nginx fails to restart. Now ask Claude Code to figure it out:

The web server on 192.168.1.50 is down. Figure out why and fix it.

Claude Code runs through its own diagnostic sequence without being told what to check:

Step 1: Check service status
$ ssh [email protected] "systemctl status nginx"
→ Active: failed (Result: exit-code)

Step 2: Read the error log
$ ssh [email protected] "journalctl -u nginx --no-pager -n 20"
→ nginx: [emerg] unexpected "}" in /etc/nginx/nginx.conf:84

Step 3: Validate the config
$ ssh [email protected] "nginx -t"
→ nginx: configuration file test failed

Step 4: Inspect the broken line
$ ssh [email protected] "sed -n '80,90p' /etc/nginx/nginx.conf"
→ Found missing semicolons on line 84

Step 5: Fix the syntax error
$ ssh [email protected] "sed -i '84s/$/;/' /etc/nginx/nginx.conf"

Step 6: Re-validate
$ ssh [email protected] "nginx -t"
→ configuration file test is successful

Step 7: Restart and verify
$ ssh [email protected] "systemctl restart nginx && systemctl is-active nginx"
→ active

The full debugging loop took about 30 seconds. Claude Code followed the same sequence an experienced sysadmin would: check status, read the journal, validate config, find the line, fix it, re-validate, restart. It does it faster because it doesn’t pause between commands. For more on managing services, the systemctl commands reference covers the essentials.

Demo 5: Generate Kubernetes Manifests

Kubernetes YAML is verbose and easy to get wrong. Claude Code generates manifests with production defaults that most engineers forget to include.

Generate a Kubernetes deployment for a Node.js app: 3 replicas,
resource limits, liveness probe on /health, readiness probe on /ready,
ClusterIP service on port 3000. Validate with --dry-run=client.

Claude Code produces the deployment and service manifests with best-practice defaults:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  labels:
    app: nodeapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nodeapp
  template:
    metadata:
      labels:
        app: nodeapp
    spec:
      containers:
      - name: nodeapp
        image: nodeapp:1.0.0
        ports:
        - containerPort: 3000
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 256Mi
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 15
        readinessProbe:
          httpGet:
            path: /ready
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: nodeapp
spec:
  type: ClusterIP
  selector:
    app: nodeapp
  ports:
  - port: 3000
    targetPort: 3000

Resource requests, limits, and both probe types are included by default. The image tag uses a specific version (not latest). Claude Code adds these because it understands Kubernetes best practices, not because you asked for each one explicitly. After the dry-run validates, apply to a real cluster. The kubectl cheat sheet covers the commands you’ll use to inspect the deployment.

Demo 6: Headless Mode in CI/CD

Claude Code runs non-interactively with the -p flag. Pipe a Terraform plan into it for automated security review:

terraform plan -out=tfplan
terraform show -json tfplan | claude -p "Review this plan. Flag security issues, unexpected destroys, or missing tags. Output as markdown."

In GitHub Actions, the official anthropics/claude-code-action posts review comments directly on pull requests. This catches misconfigurations before they reach production.

Bulk operations work the same way:

git diff main --name-only -- '*.tf' | claude -p "Review these changed Terraform files for security issues and best practice violations"

Pipe changed files, log output, or test results into Claude Code and it processes them in a single pass. If you need to install Terraform on your Linux workstation first, handle that before trying the pipeline demos. The Claude Code in GitHub Actions guide covers the full CI/CD integration.

Setting Up CLAUDE.md for Infrastructure Projects

This section separates “tried it once” from “my team uses it safely every day.” The CLAUDE.md file sits in your project root and tells Claude Code what it can and cannot do. For infrastructure repos, the rules must be explicit. For a full breakdown of the directory structure, see the .claude directory guide.

Here is a production-grade CLAUDE.md for a DevOps repository:

# Infrastructure Repo Rules

## Safety (NON-NEGOTIABLE)
- NEVER run `terraform apply` without `terraform plan` first
- NEVER run `terraform destroy` without explicit user confirmation
- NEVER run `terraform state rm` or `terraform state mv` without confirmation
- NEVER run `kubectl delete namespace` or `kubectl delete pv` without confirmation
- NEVER disable SELinux (`setenforce 0`) on any server
- ALWAYS run `ansible-playbook --check` before the real run on first execution
- ALWAYS use `--dry-run=client` with `kubectl apply` on first attempt
- NEVER hardcode credentials, API keys, or passwords in any file

## Terraform
- State files are in remote backend. Never modify state directly
- Run `terraform validate` after every .tf change
- Tag all resources: environment, project, managed-by=terraform
- Always plan with `-out=tfplan` and apply from the saved plan

## Ansible
- Hosts defined in inventory files, not hardcoded
- Use `ansible-vault` for sensitive variables
- Playbooks must be idempotent (use built-in modules, not shell/command)
- Include a verification task at the end of each play

## Kubernetes
- Always specify resource requests and limits
- Never deploy to default namespace
- Include liveness and readiness probes
- Never use `latest` tag in production manifests

## Docker
- Multi-stage builds to minimize image size
- Run as non-root user
- Never copy secrets into images

Claude Code reads this file at the start of every session. If you ask it to run terraform destroy, it refuses. If you ask it to write an Ansible playbook, it uses proper modules and role structure. These are strong guidelines, not OS-level enforcement. For hard enforcement, use permission rules.

Permission Lockdown with settings.json

Claude Code reads permissions from two files. Global settings protect every project. Project settings fine-tune what’s allowed in a specific repo.

FileScopeWhat Goes HereShared?
~/.claude/settings.jsonAll projectsUniversal safety: rm -rf /, mkfs, piping curl to bashNo (personal)
.claude/settings.jsonThis repo onlyProject-specific Terraform, Ansible, kubectl rulesYes (commit to Git)

Global (~/.claude/settings.json). Set once, protects every project:

{
  "permissions": {
    "deny": [
      "Bash(rm -rf /*)",
      "Bash(mkfs*)",
      "Bash(dd if=*of=/dev/*)",
      "Bash(chmod -R 777*)",
      "Bash(curl*|*bash*)",
      "Bash(wget*|*bash*)"
    ]
  }
}

Project (.claude/settings.json). Committed to Git, inherited by every team member who clones:

{
  "permissions": {
    "allow": [
      "Bash(terraform init*)",
      "Bash(terraform validate*)",
      "Bash(terraform plan*)",
      "Bash(terraform fmt*)",
      "Bash(terraform show*)",
      "Bash(ansible-playbook --check*)",
      "Bash(ansible-lint*)",
      "Bash(kubectl get*)",
      "Bash(kubectl describe*)",
      "Bash(kubectl logs*)",
      "Bash(docker build*)",
      "Bash(docker ps*)",
      "Bash(helm list*)",
      "Bash(helm template*)"
    ],
    "deny": [
      "Bash(terraform destroy*)",
      "Bash(terraform apply -auto-approve*)",
      "Bash(terraform state rm*)",
      "Bash(kubectl delete namespace*)",
      "Bash(kubectl delete pv *)",
      "Bash(helm uninstall*)"
    ]
  }
}

Read-only operations run without prompting. Destructive operations are blocked entirely. Everything in between asks for approval. Deny rules from either file stack, so global catches universally dangerous commands while project rules handle tool-specific restrictions.

Validation Hooks

Hooks run shell commands before or after Claude Code actions. For infrastructure, the most valuable hook auto-validates Terraform files after every edit. Add this to your project .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if echo \"$CLAUDE_FILE_PATHS\" | grep -q '\\.tf$'; then terraform validate 2>&1 || true; fi"
          }
        ]
      },
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if echo \"$CLAUDE_FILE_PATHS\" | grep -qE '\\.ya?ml$'; then yamllint -d relaxed \"$CLAUDE_FILE_PATHS\" 2>&1 || true; fi"
          }
        ]
      }
    ]
  }
}

Every time Claude Code edits a .tf file, the hook runs terraform validate automatically. YAML files (Ansible playbooks, Kubernetes manifests) get linted. If validation fails, Claude Code sees the error and fixes it immediately. For the full hooks API, see the official hooks documentation.

Security: What You Must Know

Claude Code inherits every credential in your shell environment. This is what makes it powerful for DevOps, and also what makes it risky without guardrails.

Use credential managers, not environment variables. Instead of exporting AWS_ACCESS_KEY_ID in your shell profile, use aws-vault to inject temporary credentials into the Claude Code session:

aws-vault exec staging -- claude

This starts Claude Code with temporary AWS credentials scoped to the staging environment. They expire automatically when the session ends.

Audit MCP servers before installing. MCP (Model Context Protocol) extends Claude Code with external tool integrations. A February 2026 study by Snyk found that 13.4% of public MCP skills had critical vulnerabilities, with 76 confirmed malicious payloads. Only install skills from trusted sources and review their code first.

Know when NOT to use Claude Code:

  • Production Terraform state manipulation: state corruption is painful and Claude does not fully understand complex dependency graphs
  • Secrets rotation: use Vault, AWS Secrets Manager, or sealed-secrets instead
  • Compliance environments: SOC 2, HIPAA, PCI DSS need audit trails that terminal history doesn’t satisfy
  • Multi-tenant credential access: if one credential set touches multiple customer environments, the blast radius is unacceptable
  • Disaster recovery procedures: one wrong command in a cascade scenario can make things worse

What Claude Code Gets Wrong

No honest guide skips the limitations. After extensive testing with infrastructure tasks:

  • Complex Terraform module composition across environments with shared state. Single modules work well, but wiring many modules with cross-references sometimes produces circular dependencies
  • Provider-specific edge cases. IAM policies with complex conditions, advanced VPC peering, and multi-region setups sometimes produce configs that validate but don’t behave as intended
  • Ansible idempotency. Generated playbooks occasionally use command or shell modules where a proper built-in module exists. This works once but isn’t idempotent on re-runs
  • Kubernetes networking. Network policies, service mesh configurations, and cross-namespace communication rules need careful review
  • SELinux contexts. On RHEL/Rocky systems, Claude Code sometimes forgets to set proper SELinux contexts after creating files or changing ports. Always verify with ausearch -m avc -ts recent

The rule: always review the plan, always test in staging, never auto-apply to production. Claude Code accelerates the work, but the engineer makes the final call.

Quick Reference: When to Use It

TaskUse Claude Code?Safety Approach
Generate a new Terraform moduleYesReview plan before applying
Debug a failing Ansible playbookYesRun with --check first
Write a Dockerfile from scratchYesReview image, scan for vulnerabilities
Create Kubernetes manifestsYes--dry-run=client then review
SSH diagnostics across serversYesRead-only commands by default
Set up a CI/CD pipelineYesReview YAML before merge
Rotate production secretsNoVault or Secrets Manager
Modify Terraform stateNoManual with backup
Deploy without reviewNoAlways review first
Multi-tenant credential workNoIsolate per tenant

The Hands-On Series

This guide gives you the foundation and safety configuration. Each tool gets a dedicated deep-dive with full demos on real infrastructure:

GuideWhat You Will BuildTested On
Claude Code + SSHProvision servers, diagnose failures, multi-server health checksOpenStack VMs
Claude Code + TerraformGenerate modules, deploy real infra, import resources, safety hooksOpenStack / AWS
Claude Code + AnsibleGenerate playbooks, convert scripts to roles, debug SELinux denialsRocky Linux 10 + Ubuntu 24.04
Claude Code + DockerMulti-stage builds, Compose stacks, optimization, container debuggingDocker on Linux
Claude Code + KubernetesManifests, Helm charts, pod log analysis, debugging CrashLoopBackOffMinikube / real cluster
Claude Code + GitHub ActionsAutomated PR review, Terraform validation pipelineGitHub repository

Every guide in the series follows the same pattern: real prompt, real generated code, real execution, verified result. When commands differ between Rocky Linux and Ubuntu, both variants are shown. Every guide uses real prompts, real infrastructure, and verified output.

Frequently Asked Questions

Can Claude Code manage multiple servers at once?

Yes. Claude Code SSHes into servers sequentially, runs commands on each, and aggregates the output into a single report. It can also spawn subagents that work on different servers in parallel. For inventory gathering, health checks, and log collection across a fleet, it replaces opening multiple terminal tabs. The limitation is that each SSH command must be non-interactive (no vi, no interactive prompts).

Does Claude Code work with private Git repos and internal tools?

Yes. It inherits your Git configuration, SSH keys, and any CLI tools in your PATH. Private repositories work if your SSH agent or credential helper is configured. Internal CLIs and APIs work as long as they have non-interactive modes. MCP servers can extend Claude Code’s reach to internal services like Jira, Confluence, or custom monitoring dashboards.

How do I prevent Claude Code from accessing production?

Three layers work together. First, use separate kubeconfig and AWS profile files per environment and set the env var to staging before starting Claude Code. Second, add production hostnames and cluster contexts to your deny rules in ~/.claude/settings.json. Third, run Claude Code in a devcontainer or isolated shell that only mounts staging credentials. The global deny rules persist across every session and every project.

What happens if Claude Code breaks something?

Recovery depends on the tool. Terraform: the saved plan file and state history protect you. Ansible: idempotent playbooks can re-run safely. Kubernetes: kubectl rollout undo reverts deployments. File edits: Claude Code’s session history shows every change and you can ask it to revert. The key is always having a rollback path before letting Claude Code execute anything destructive.

Related Articles

AI Setup Aider – AI Pair Programming in Your Terminal AI Deploy Infrastructure with Claude Code and Terraform AI How To Install LibreOffice 25.x on CentOS 9 | RHEL 9 AI Top 10 AI Tools for Developers in 2025

Leave a Comment

Press ESC to close