Automating a Simple SAP Lab Environment with Terraform and Ansible

This walkthrough demonstrates how to provision a lightweight SLES instance using Terraform, then automatically configure it using Ansible. The result is a clean, automated pipeline that can build and prepare a small SAP-style lab environment in minutes.

All identifying information (AWS account details, VPC IDs, Subnets, AMI IDs, SSH key names, IP addresses, etc.) is represented using placeholders.

Overview

This setup uses two main components:

1. Terraform (Infrastructure)

A SLES EC2 instanceA minimal security groupAn SSH key pair referenceAn Ansible-ready inventory line (via Terraform outputs)

2. Ansible (Configuration)

Basic packageschronyd for time synchronisationSimple SAP-friendly sysctl tuning

No SAP software is installed here. This is a lightweight foundation for further SAP experimentation.

Directory Structure

sap-lab/
├── run.sh
├── run_destroy.sh

├── terraform/
│ ├── main.tf
│ ├── <SSH_PUBLIC_KEY_FILENAME>.pub
│ └── terraform.tfstate (generated automatically)

└── ansible/
├── inventory.ini
├── site.yml
└── ansible.cfg

Terraform: main.tf

The following main.tf provisions a SLES instance and generates an Ansible inventory line.

terraform {
required_version = “>= 1.5”

required_providers {
aws = {
source = “hashicorp/aws”
version = “~> 5.0”
}
}
}

provider “aws” {
region = “<AWS_REGION>” # e.g. us-east-2
}

resource “aws_key_pair” “ssh_key” {
key_name = “<KEY_NAME>” # e.g. sap-lab-key
public_key = file(“${path.module}/<SSH_PUBLIC_KEY_FILENAME>.pub”)
}

resource “aws_security_group” “sap_host_sg” {
name = “sap-host-sg”
description = “Security group for SAP lab host”
vpc_id = “<VPC_ID>”

ingress {
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”] # adjust for production
}

egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}

tags = {
Name = “sap-host-sg”
}
}

resource “aws_instance” “sap_host” {
ami = “<SLES_AMI_ID>” # generic placeholder
instance_type = “t2.micro”
key_name = aws_key_pair.ssh_key.key_name

subnet_id = “<SUBNET_ID>”
associate_public_ip_address = true

vpc_security_group_ids = [
aws_security_group.sap_host_sg.id
]

tags = {
Name = “SAP-LAB-Host”
}
}

output “ansible_inventory_line” {
description = “Ansible inventory line for this host”
value = “sap_host ansible_host=<EC2_PUBLIC_IP> ansible_user=ec2-user ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>/<SSH_PRIVATE_KEY_FILENAME>.pem ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'”
}

Ansible: site.yml


– name: Prepare host for SAP-style workloads
hosts: sap_hosts
become: true

tasks:
– name: Install basic packages
ansible.builtin.zypper:
name:
– wget
– net-tools
– chrony
state: present

– name: Ensure chronyd is enabled and running
ansible.builtin.service:
name: chronyd
state: started
enabled: yes

– name: Set SAP-friendly sysctl values
ansible.posix.sysctl:
name: vm.swappiness
value: “10”
state: present
reload: yes

Ansible: inventory.ini

[sap_hosts]
sap_host ansible_host=<EC2_PUBLIC_IP> ansible_user=ec2-user ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>/<SSH_PRIVATE_KEY_FILENAME>.pem ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null’

Automation script: run.sh

#!/usr/bin/env bash
set -e

echo “=== Terraform apply ===”
cd terraform
terraform init -input=false
terraform apply -auto-approve -input=false

echo “=== Extracting host info for Ansible ===”
INVENTORY_LINE=$(terraform output -raw ansible_inventory_line)

cd ../ansible

echo “=== Writing inventory.ini ===”
{
echo “[sap_hosts]”
echo “$INVENTORY_LINE”
} > inventory.ini

echo “=== Running Ansible playbook ===”
ansible-playbook -i inventory.ini site.yml

Automation script: run_destroy.sh

#!/usr/bin/env bash
set -e

echo “=== Terraform destroy ===”
cd terraform
terraform destroy -auto-approve -input=false
cd ..

echo “=== Clearing Ansible inventory ===”
echo “# Inventory cleared after destroy” > ansible/inventory.ini

Running the lab

Build the environment

./run.sh

Destroy the environment

./run_destroy.sh

Conclusion

This tutorial provides a simple, repeatable way to spin up SAP-friendly Linux hosts on AWS: Terraform handles the infrastructure, and Ansible handles configuration. From here, you can extend the playbook with SAP Host Agent installation, Cloud Connector setup, or full SAP system preparation, while keeping the core workflow automated and reproducible.

 

​ This walkthrough demonstrates how to provision a lightweight SLES instance using Terraform, then automatically configure it using Ansible. The result is a clean, automated pipeline that can build and prepare a small SAP-style lab environment in minutes.All identifying information (AWS account details, VPC IDs, Subnets, AMI IDs, SSH key names, IP addresses, etc.) is represented using placeholders.OverviewThis setup uses two main components:1. Terraform (Infrastructure)A SLES EC2 instanceA minimal security groupAn SSH key pair referenceAn Ansible-ready inventory line (via Terraform outputs)2. Ansible (Configuration)Basic packageschronyd for time synchronisationSimple SAP-friendly sysctl tuningNo SAP software is installed here. This is a lightweight foundation for further SAP experimentation.Directory Structuresap-lab/
├── run.sh
├── run_destroy.sh

├── terraform/
│ ├── main.tf
│ ├── <SSH_PUBLIC_KEY_FILENAME>.pub
│ └── terraform.tfstate (generated automatically)

└── ansible/
├── inventory.ini
├── site.yml
└── ansible.cfgTerraform: main.tfThe following main.tf provisions a SLES instance and generates an Ansible inventory line.terraform {
required_version = “>= 1.5”

required_providers {
aws = {
source = “hashicorp/aws”
version = “~> 5.0”
}
}
}

provider “aws” {
region = “<AWS_REGION>” # e.g. us-east-2
}

resource “aws_key_pair” “ssh_key” {
key_name = “<KEY_NAME>” # e.g. sap-lab-key
public_key = file(“${path.module}/<SSH_PUBLIC_KEY_FILENAME>.pub”)
}

resource “aws_security_group” “sap_host_sg” {
name = “sap-host-sg”
description = “Security group for SAP lab host”
vpc_id = “<VPC_ID>”

ingress {
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”] # adjust for production
}

egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}

tags = {
Name = “sap-host-sg”
}
}

resource “aws_instance” “sap_host” {
ami = “<SLES_AMI_ID>” # generic placeholder
instance_type = “t2.micro”
key_name = aws_key_pair.ssh_key.key_name

subnet_id = “<SUBNET_ID>”
associate_public_ip_address = true

vpc_security_group_ids = [
aws_security_group.sap_host_sg.id
]

tags = {
Name = “SAP-LAB-Host”
}
}

output “ansible_inventory_line” {
description = “Ansible inventory line for this host”
value = “sap_host ansible_host=<EC2_PUBLIC_IP> ansible_user=ec2-user ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>/<SSH_PRIVATE_KEY_FILENAME>.pem ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'”
}Ansible: site.yml—
– name: Prepare host for SAP-style workloads
hosts: sap_hosts
become: true

tasks:
– name: Install basic packages
ansible.builtin.zypper:
name:
– wget
– net-tools
– chrony
state: present

– name: Ensure chronyd is enabled and running
ansible.builtin.service:
name: chronyd
state: started
enabled: yes

– name: Set SAP-friendly sysctl values
ansible.posix.sysctl:
name: vm.swappiness
value: “10”
state: present
reload: yesAnsible: inventory.ini[sap_hosts]
sap_host ansible_host=<EC2_PUBLIC_IP> ansible_user=ec2-user ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>/<SSH_PRIVATE_KEY_FILENAME>.pem ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null’Automation script: run.sh#!/usr/bin/env bash
set -e

echo “=== Terraform apply ===”
cd terraform
terraform init -input=false
terraform apply -auto-approve -input=false

echo “=== Extracting host info for Ansible ===”
INVENTORY_LINE=$(terraform output -raw ansible_inventory_line)

cd ../ansible

echo “=== Writing inventory.ini ===”
{
echo “[sap_hosts]”
echo “$INVENTORY_LINE”
} > inventory.ini

echo “=== Running Ansible playbook ===”
ansible-playbook -i inventory.ini site.ymlAutomation script: run_destroy.sh#!/usr/bin/env bash
set -e

echo “=== Terraform destroy ===”
cd terraform
terraform destroy -auto-approve -input=false
cd ..

echo “=== Clearing Ansible inventory ===”
echo “# Inventory cleared after destroy” > ansible/inventory.iniRunning the labBuild the environment./run.shDestroy the environment./run_destroy.shConclusionThis tutorial provides a simple, repeatable way to spin up SAP-friendly Linux hosts on AWS: Terraform handles the infrastructure, and Ansible handles configuration. From here, you can extend the playbook with SAP Host Agent installation, Cloud Connector setup, or full SAP system preparation, while keeping the core workflow automated and reproducible.   Read More Technology Blog Posts by Members articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author