- Posted on
- • Artificial Intelligence
Artificial Intelligence Terraform on Linux
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Terraform on Linux: Reproducible AI Infrastructure from Your Terminal
If you’ve ever burned a day clicking through cloud consoles to spin up a GPU box “just to test an idea,” you know the pain: inconsistent setups, forgotten security rules, surprise bills, and fragile environments you can’t reproduce. Terraform on Linux solves that. Treat your AI infrastructure as code, stamp out identical GPU machines on demand, attach storage for datasets, bootstrap frameworks automatically, and tear it all down when you’re done—all from Bash.
This guide explains why AI + Terraform on Linux is a winning combo and walks you through a practical, repeatable setup. You’ll get installation instructions for apt, dnf, and zypper, and a real-world Terraform example to provision a GPU-ready VM with object storage and a bootstrap script for your frameworks.
Why Terraform for AI on Linux?
Repeatability: Your infra is code. Re-run it to get the same environment every time.
Speed: New GPU boxes spin up in minutes with your preferred stack pre-baked.
Cost control: Ephemeral clusters and automated teardown reduce idle spend.
Portability: The same Terraform patterns work across AWS, Azure, GCP, and on-prem.
Team-friendly: Version, review, and automate infra changes like software.
Prerequisites: Install Terraform and CLI Essentials
You’ll need:
Terraform
Common CLI tools: curl, unzip, git, jq
A cloud account (example uses AWS) and credentials configured (e.g., environment variables or a profile)
Note: Always follow your distro’s best practices and verify keys/repositories. The commands below use official HashiCorp repositories.
Debian/Ubuntu (apt)
sudo apt update
sudo apt install -y curl unzip git jq gnupg lsb-release
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt install -y terraform
terraform -version
RHEL/CentOS/Alma/Rocky (dnf)
sudo dnf -y install curl unzip git jq gnupg2 dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo dnf -y install terraform
terraform -version
Fedora (dnf)
sudo dnf -y install curl unzip git jq gnupg2 dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf -y install terraform
terraform -version
openSUSE/SLES (zypper)
sudo zypper refresh
sudo zypper install -y curl unzip git jq gpg2
sudo rpm --import https://rpm.releases.hashicorp.com/gpg
sudo zypper addrepo https://rpm.releases.hashicorp.com/opensuse/hashicorp.repo
sudo zypper refresh
sudo zypper install -y terraform
terraform -version
Tip: If your distro lacks a repo, you can always install Terraform from the official releases by downloading the zip and placing the binary in /usr/local/bin.
Core Walkthrough: Provision a GPU-ready AI box with Terraform (AWS example)
This example creates:
A security group with SSH access
An S3 bucket for datasets
An IAM role with bucket access
A GPU instance with a cloud-init bootstrap script to prep your AI environment
You can adapt the same pattern to Azure/GCP by swapping the provider/resources.
1) Project scaffold
mkdir ai-terraform && cd ai-terraform
Create files: versions/providers, variables, main resources, and outputs.
versions.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
}
providers.tf
provider "aws" {
region = var.aws_region
}
variables.tf
variable "project" {
description = "Project name prefix for resources"
type = string
default = "ai-terraform-demo"
}
variable "aws_region" {
description = "AWS region"
type = string
default = "us-east-1"
}
variable "instance_type" {
description = "GPU instance type (e.g., g5.xlarge, g4dn.xlarge)"
type = string
default = "g5.xlarge"
}
variable "key_name" {
description = "Existing EC2 key pair for SSH"
type = string
}
variable "ami_id" {
description = "GPU-friendly AMI ID (e.g., AWS Deep Learning AMI for your region)"
type = string
}
variable "ssh_cidr" {
description = "CIDR allowed to SSH (restrict to your IP)"
type = string
default = "0.0.0.0/0"
}
variable "bucket_name" {
description = "Optional S3 bucket name; leave null to auto-generate"
type = string
default = null
}
main.tf
data "aws_vpc" "default" {
default = true
}
resource "aws_security_group" "ssh" {
name = "${var.project}-ssh"
description = "Allow SSH"
vpc_id = data.aws_vpc.default.id
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.ssh_cidr]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${var.project}-ssh" }
}
resource "random_id" "rand" {
byte_length = 4
}
resource "aws_s3_bucket" "data" {
bucket = var.bucket_name != null ? var.bucket_name : "${var.project}-${random_id.rand.hex}"
force_destroy = true
tags = { Project = var.project }
}
data "aws_iam_policy_document" "assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "s3" {
statement {
actions = ["s3:*"]
resources = [aws_s3_bucket.data.arn, "${aws_s3_bucket.data.arn}/*"]
}
}
resource "aws_iam_role" "ec2" {
name = "${var.project}-ec2-role"
assume_role_policy = data.aws_iam_policy_document.assume.json
}
resource "aws_iam_role_policy" "s3_access" {
name = "${var.project}-s3-policy"
role = aws_iam_role.ec2.id
policy = data.aws_iam_policy_document.s3.json
}
resource "aws_iam_instance_profile" "s3_profile" {
name = "${var.project}-instance-profile"
role = aws_iam_role.ec2.name
}
resource "aws_instance" "gpu" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.ssh.id]
iam_instance_profile = aws_iam_instance_profile.s3_profile.name
root_block_device {
volume_size = 100
volume_type = "gp3"
}
user_data = base64encode(templatefile("${path.module}/cloud-init.yaml", {
project = var.project
bucket_name = aws_s3_bucket.data.bucket
}))
tags = {
Name = "${var.project}-gpu"
Project = var.project
}
}
cloud-init.yaml
#cloud-config
package_update: true
packages:
- git
- htop
write_files:
- path: /opt/bootstrap.sh
permissions: '0755'
owner: root:root
content: |
#!/usr/bin/env bash
set -euxo pipefail
echo "Project: ${project}" > /etc/motd
# Ensure a Python environment is available. If DLAMI is used, conda already exists.
if ! command -v conda >/dev/null 2>&1; then
curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh
bash /tmp/miniconda.sh -b -p /opt/miniconda
echo 'export PATH=/opt/miniconda/bin:$PATH' > /etc/profile.d/conda.sh
fi
source /etc/profile.d/conda.sh || true
conda init bash || true
conda create -y -n ai python=3.10
source /opt/miniconda/bin/activate ai || true
# Try GPU wheels first (expects an image with CUDA drivers, e.g., AWS DLAMI). Fallback to CPU.
pip install --upgrade pip
(pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121) || \
(pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu)
python - <<'PY'
import torch, platform
print("Python:", platform.python_version())
print("Torch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
PY
# Prepare a data directory mounted to S3 with AWS CLI if desired (CLI not preinstalled here).
mkdir -p /opt/data
echo "Bucket: ${bucket_name}" >> /var/log/bootstrap.log
runcmd:
- [ bash, -lc, "/opt/bootstrap.sh > /var/log/bootstrap.log 2>&1" ]
outputs.tf
output "instance_public_ip" {
value = aws_instance.gpu.public_ip
}
output "s3_bucket_name" {
value = aws_s3_bucket.data.bucket
}
output "ssh_command" {
value = "ssh -i ~/.ssh/${var.key_name}.pem ubuntu@${aws_instance.gpu.public_ip}"
}
Notes:
For AMI: Choose a GPU-friendly image in your region. Using an AWS Deep Learning AMI (DLAMI) with NVIDIA drivers preinstalled makes the bootstrap script seamless. Set var.ami_id accordingly.
For username: Ubuntu AMIs typically use the ubuntu user; adjust for other distros (ec2-user, centos, etc.).
Restrict ssh_cidr to your IP, not 0.0.0.0/0, for security.
2) Initialize and apply
terraform init
terraform validate
terraform plan -out tfplan
terraform apply tfplan
When apply finishes, Terraform prints the instance IP, S3 bucket, and an SSH command. Connect and inspect logs:
ssh -i ~/.ssh/YOUR_KEY.pem ubuntu@PUBLIC_IP
sudo tail -f /var/log/bootstrap.log
If you used a DLAMI, you should see CUDA available: True. If you used a generic AMI, the script falls back to CPU wheels.
3) Move datasets in and out (S3)
Use the created bucket to store datasets, checkpoints, and artifacts. From your laptop you can sync a local folder:
aws s3 sync ./datasets s3://YOUR_BUCKET/datasets
On the instance, your training code can access S3 directly thanks to the attached IAM role (no static keys needed).
4) Repeatability tips that save time and money
Variables and tfvars: Keep different sizes/regions in .tfvars files and switch quickly with -var-file.
Cloud-init > remote provisioners: Prefer bootstrap scripts via user_data for immutable, self-configuring hosts.
Tags everywhere: Add Project, Owner, TTL tags and enforce cleanup with CI or lambda crons.
Remote state: Store state in an encrypted backend (e.g., S3 + DynamoDB lock) to collaborate safely.
Destroy when done: Ephemeral is cheaper. One command:
terraform destroy
5) Real-world examples
Quick R&D: One GPU instance + S3 bucket for dataset staging; run experiments, push metrics to your tracker, destroy nightly.
Team template: A module that creates a compliant GPU node with your org’s base image, logging agents, and budget tags.
Dataset jobs: Spin a CPU spot-fleet module for preprocessing, and a separate GPU module only for training windows.
Common variations
Different clouds: Swap the provider and equivalent resources (Azure VM + Managed Identity + Blob Storage; GCP Compute + Service Account + GCS).
Local labs: Use Terraform + libvirt or VMware providers to build reproducible local GPU workstations (ensure host drivers and passthrough).
Kubernetes: Use Terraform to stand up managed clusters (EKS/AKS/GKE) with GPU node groups and deploy training jobs via Helm charts.
Conclusion and Next Steps
With Terraform on Linux, your AI infrastructure becomes a fast, reproducible, and teardown-friendly part of your workflow. No more snowflake servers—just clean, documented code that spins up exactly what you need, when you need it.
Your next steps:
Install Terraform using apt, dnf, or zypper.
Clone this pattern into a private repo and parameterize it for your cloud and images.
Add remote state, cost tags, and CI to plan/apply automatically.
Expand to modules (gpu-node, dataset-bucket, training-job) for reuse across projects.
Questions or want a version for Azure/GCP/Kubernetes? Ask, and I’ll adapt this template to your stack.