How to Generate Terraform Code with AI: Claude + GitHub MCP Tutorial

Learn how to use Claude AI with GitHub MCP to automatically generate secure Terraform infrastructure code. Step-by-step guide with real Azure deployment examples, including NAT Gateway and Application Gateway configurations.


Introduction

What if you could cut your Infrastructure as Code automation development time by up to 75%? In this guide, we'll use Claude Sonnet 4.5 with GitHub's Model Context Protocol (MCP) to automatically refactor a basic Azure lab environment into a production-grade, secure infrastructure—all through natural language prompts.

We'll transform an insecure Linux VM setup with a public IP into a properly secured environment using Azure security hardening. The exciting part? We'll let AI determine the optimal resources and architecture needed for secure ingress and egress.

It'll be interesting to see how the AI-generated solution compares to what I would design as a Microsoft Certified: Azure Administrator Associate.

Table of Contents

What You'll Learn

By the end of this tutorial, you'll be able to:

  • Configure Claude Desktop with GitHub MCP for Infrastructure as Code
  • Write effective prompts for AI-assisted Terraform development
  • Automatically generate secure Azure networking resources
  • Identify and fix AI-generated code issues
  • Apply production security patterns to lab environments

Our Source Environment

In this lab, we are starting off with a GitHub Repository that contains the infrastructure used for the Learning Linux Series:

This setup is fine for basic learning, but the security is questionable. The Linux VM has a public IP address facing the Internet directly, and is only protected by a Network Security Group (NSG) Rules.

The Desired Outcome

We want to improve the Ingress and Egress security by adding Azure Resources like it's done in production environments. I expect at least the following changes:

  • The Public IP is no longer assigned to the Linux VM
  • A NAT Gateway is used for Egress traffic
  • A Load Balancer is used for Ingress traffic. An Application Gateway would be even better, because it can do SSL Termination in future labs.

Methodology

We are going to use Claude Desktop integrated with GitHub Official MCP Server to prompt Claude to make the changes for us. The prompts are crucial for getting the desired outcome. Claude is good at reading human-like prompts, but please be aware that it can get a little too creative sometimes. The prompts need to be specific and clear, and you need to give it a scope to narrow down the outcome.

Putting Claude to Work

MCP is in its early stages and many features are still experimental. Expect bugs and errors. Always review carefully and test the code output properly before considering implementing in production.

Prerequisites

  • Claude Desktop installed
  • Docker Desktop 4.35+ (with MCP Toolkit support)
  • GitHub Official MCP Server configured in Docker Desktop
  • A GitHub Account with a repository to test
  • GitHub Personal Access Token (PAT) with repo permissions
  • Claude Pro Account (for Claude Desktop app access). Highly recommended, as the free version has limited capabilities.
  • An Azure Subscription (for deploying the Terraform code later)
  • Terraform CLI installed locally (for deploying the Terraform code later)
  • Terraform State Storage Account and Container (for storing the Terraform state remotely). Highly recommended, make good habits using Terraform best practices from the start.

The Main Prompt

We need to give Claude a clear and concise prompt to get the desired outcome. Prompting is an art, and it takes some practice to get it right. Every LLM has its own quirks, and you need to learn how to communicate with it. Here is the main prompt I pasted in to Claude Desktop for this lab:

# Improve Ingress and Egress
 
You are an AI based DevOps expert with extensive knowledge in IaC like
Terraform and how to manage Github repositories as well as documentation best
practises. I want to improve Ingress and Egress to a Web Server running on a
Linux VM.
 
## Repo info
 
- GitHub account: jihillestad
- Repo: tflab-linux
- Repo type: Private
- Project type: Terraform IaC for creating a simple landing zone and a Linux VM
 
## Scope
 
- CI/CD is not implemented. Ignore CI/CD.
- Single VNET simple environment. Ignore Hub and Spoke
 
## Request
 
- Create a Feature Branch for improving Ingress and Egress to the Azure Environment
- All improvements are to be done in the new Feature Branch only. Do not touch the main branch.
- Make a secure Ingress for the Linux VM. Remove the Public IP from the VM, and
  add it to the best resource for our Ingress. Make sure the Ingress can connect
  to the Private IP of the Linux VM
- Make sure the VM has a safe Egress. It needs Internet Access to download
  packages.

Executing the Prompt (⏱️ ~15 minutes)

  1. Open Claude Desktop and create a new chat. Make sure the MCP server is active.

    Claude Desktop MCP Server active status
  2. Paste the prompt in to the chat and hit "Send".

    Pasting the prompt in to Claude Desktop
  3. Wait for Claude to respond. It might take a while, depending on the complexity of the prompt and the current load on the servers.

  4. Review Claude's suggested actions carefully. Approve as needed. In this case, I approved all the changes.

    The Claude Desktop chat crashed on me 2 times. I'm sorry there's no image to share.

    When there is no more activity in the chat, Claude is done processing. Move on to the next step.

  5. Open your GitHub repository in a web browser. You should see a new branch created by Claude.

    GitHub new branch created by Claude
  6. Compare the new branch with the main branch. You should see the commits that Claude made.

    GitHub compare branches
  7. Review the changes carefully. Make sure you understand what Claude did. Here's an example confirming that Claude removed the Public IP from the NIC assigned to the Linux VM:

    GitHub code changes

    Once you are satisfied with the changes, it's time to test the code.

Claude has saved us a lot of time. It took me about 15 minutes to run the prompt and review the outcome. Doing this manually would have taken me at least 1-2 hours.

The outcome, High Level

  • A new branch called feature/improve-ingress-egress was created
  • The Public IP was removed from the Linux VM NIC
  • Egress solution: A NAT Gateway was created
  • Ingress solution: An Application Gateway was created with a Public IP.
  • The Virtual Machine is no longer exposed to the Internet directly
  • The Terraform Code needs some cleanup. There is definitely room for improvement. Some resources are not in the right tf files, and there are some repetitive code blocks that could be handled with locals or modules according to the DRY principle.

Testing the Changes (⏱️ ~30 minutes)

Now it's time to test the changes. We need to make sure everything works as expected. This is a crucial step, as AI-generated code can have bugs or oversights. Always have a human in the loop to catch any mistakes.

  1. Fetch the changes to your local machine and switch to the new branch.

    git fetch --all
    git switch feature/improve-ingress-egress
  2. Log in to Azure CLI and set the necessary Terraform environment variables.

  3. terraform init to initialize the working directory. Use the needed parameters for your Terraform Backend.

  4. Let's try to catch the first bugs by running terraform validate. Caught One:

    Terraform Validate Error

    Claude missed this Terraform Output, fixed it by commenting it out. Humans to the rescue!

    Fixed Terraform Output
  5. Run terraform plan to see what changes will be made. Everything looks good.

  6. Run terraform apply --auto-approve to apply the changes. Wait for the deployment to complete. Caught another one:

    Terraform Apply Error

    Pro Tip: Most AI-generated Terraform code will have 1-2 issues that only surface during terraform apply. This is normal and actually demonstrates the importance of the testing phase. Common issues include subnet overlaps, incorrect resource dependencies, or missing outputs.

  7. Let's fix the error by changing the netnum parameter in to something appropriate:

    Fixed subnet overlap

    Pardon my French, Claude. Human Power to the rescue again!

  8. Run terraform apply --auto-approve again. This time it worked. Verify the changes in the Azure Portal. Everything looks good.

  9. Commit the changes and push the branch back to GitHub.

  10. Connect to your Linux VM using Azure Bastion. Update and upgrade the apt packages to verify that the VM has Internet Access.

  11. Install apache2 web server. We need something to test the Ingress.

  12. Open a web browser and navigate to the Public IP of the Application Gateway Frontend. You should see the Apache2 default page.

    Apache2 default page
  13. Run terraform destroy --auto-approve to clean up the resources. Keeping this running is definitely not for free.

Conclusion

Using AI to generate Terraform code from GitHub repositories can save a lot of time and effort. However, it's important to review the code carefully and test it thoroughly before deploying to production. AI is a powerful tool, but it's not perfect. Always have a human in the loop to catch any mistakes or oversights.

I saved almost 2 hours of work by using Claude to generate the code for me. Prompting and reviewing took me 15 minutes. Troubleshooting took me 15 minutes. This has great value, I'll continue to explore this further.

There is room for improvements in the prompt as well as the generated code. We could instruct Claude to refactor according to KISS and DRY principles, and improve documentation. I'll let you explore that on your own, and I'll play around with it as well. This post would be way too long if I included everything.

Next Steps

Ready to take this further? Try these follow-up experiments:

  • Implement SSL termination on the Application Gateway
  • Set up Auto Scaling for the Linux VM
  • Implement Hub & Spoke network architecture
  • Add CI/CD pipelines for automated deployments. This post explains how: Terraform and CICD - keeping IaC safe

Share your results and prompt improvements in the comments below!