I’ve spent a bit of time experimenting with Cloud Connectors recently and wanted a faster, cleaner way to spin one up without all the usual hassle. In this post, I build on the earlier SCC and Ansible write-ups and bring everything together into a single workflow. We’ll automate the entire deployment using Terraform for provisioning and Ansible for configuration, resulting in a fully working SCC with minimal manual effort.
This guide provides a fully working, fully automated setup using:
Terraform for provisioning the EC2 instanceAnsible for OS prep and SCC installationHeap tuning via props.ini for stable SCC operation
1. Directory layout
sap-lab/
├── run.sh
├── run_destroy.sh
│
├── terraform/
│ ├── main.tf
│ ├── variables.tf
│ ├── terraform.tfvars
│ └── <KEYPAIR_NAME>.pub
│
└── ansible/
├── site.yml
├── inventory.ini
├── ansible.cfg
└── roles/
├── sap_prep/
│ └── tasks/main.yml
└── sap_scc/
├── defaults/main.yml
├── tasks/main.yml
└── templates/scc_daemon.service.j2
2. Terraform: main.tf
terraform {
required_version = “>= 1.5”
required_providers {
aws = {
source = “hashicorp/aws”
version = “~> 5.0”
}
}
}
provider “aws” {
region = var.region
}
resource “aws_security_group” “sap_scc_sg” {
name = “sap-scc-sg”
description = “Allow SCC UI and SSH”
vpc_id = var.vpc_id
ingress {
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
ingress {
from_port = 8443
to_port = 8443
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}
}
resource “aws_instance” “sap_scc” {
ami = var.sles_ami
instance_type = “t2.micro”
key_name = var.keypair_name
subnet_id = var.subnet_id
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.sap_scc_sg.id]
tags = {
Name = “SAP-LAB-SCC”
}
}
output “ansible_inventory” {
value = “sap_host ansible_host=${aws_instance.sap_scc.public_ip} ansible_user=ec2-user ansible_ssh_private_key_file=../terraform/${var.private_key} ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'”
}
3. Terraform Variables (variables.tf)
variable “region” {}
variable “vpc_id” {}
variable “subnet_id” {}
variable “keypair_name” {}
variable “private_key” {}
variable “sles_ami” {}
4. terraform.tfvars
region = “us-east-2”
vpc_id = “vpc-xxxxxxxxxxxxxxxx”
subnet_id = “subnet-xxxxxxxxxxxx”
keypair_name = “my-keypair”
private_key = “my-keypair.pem”
sles_ami = “ami-xxxxxxxxxxxxxxxx”
5. Ansible config (ansible.cfg)
[defaults]
host_key_checking = False
retry_files_enabled = False
6. Role: OS Preparation (sap_prep/tasks/main.yml)
—
– name: Install prerequisites
zypper:
name:
– wget
– net-tools
– chrony
– unzip
– curl
state: present
– name: Ensure chronyd is running
service:
name: chronyd
state: started
enabled: yes
– name: Set vm.swappiness
ansible.posix.sysctl:
name: vm.swappiness
value: “10”
state: present
reload: yes
7. SCC Role Defaults (sap_scc/defaults/main.yml)
—
scc_version: “2.16.2”
scc_file: “sapcc-{{ scc_version }}-linux-x64.zip”
scc_install_dir: /opt/sap/scc
scc_user: sccadm
scc_group: sccadm
scc_jvm_xms: “256m”
scc_jvm_xmx: “512m”
scc_service_name: scc_daemon
8. SCC Installation Tasks (sap_scc/tasks/main.yml)
—
– name: Ensure sccadm group exists
group:
name: “{{ scc_group }}”
system: yes
– name: Ensure sccadm user exists
user:
name: “{{ scc_user }}”
group: “{{ scc_group }}”
shell: /sbin/nologin
system: yes
– name: Install prerequisites
become: yes
zypper:
name:
– unzip
– curl
– java-17-openjdk-headless
state: present
– name: Create installer directory
file:
path: /tmp/scc-installer
state: directory
– name: Upload SCC ZIP (2.16.2)
copy:
src: sapcc-2.16.2-linux-x64.zip
dest: /tmp/scc-installer/sapcc.zip
– name: Extract SCC ZIP
unarchive:
src: /tmp/scc-installer/sapcc.zip
dest: /tmp/scc-installer
remote_src: yes
– name: Locate SCC RPM
find:
paths: /tmp/scc-installer
patterns: “com.sap.scc-ui-*.rpm”
register: rpm_file
– name: Fail if SCC RPM not found
fail:
msg: “SCC RPM not found.”
when: rpm_file.matched == 0
– name: Install SCC RPM
become: yes
zypper:
name: “{{ rpm_file.files[0].path }}”
disable_gpg_check: yes
state: present
# Heap tuning
– name: Tune Xms
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘-Xms[0-9]+m’
replace: “-Xms{{ scc_jvm_xms }}”
– name: Tune Xmx
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘-Xmx[0-9]+m’
replace: “-Xmx{{ scc_jvm_xmx }}”
– name: Tune NewSize
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘NewSize=[0-9]+m’
replace: ‘NewSize=256m’
– name: Tune MaxNewSize
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘MaxNewSize=[0-9]+m’
replace: ‘MaxNewSize=256m’
– name: Enable SCC daemon
become: yes
systemd:
name: “{{ scc_service_name }}”
enabled: yes
– name: Start SCC daemon
become: yes
systemd:
name: “{{ scc_service_name }}”
state: restarted
9. Systemd Template (scc_daemon.service.j2)
[Unit]
Description=SAP Cloud Connector
After=network.target
[Service]
Type=forking
User={{ scc_user }}
Group={{ scc_group }}
ExecStart=/opt/sap/scc/go.sh -start
ExecStop=/opt/sap/scc/go.sh -stop
Restart=on-failure
[Install]
WantedBy=multi-user.target
10. site.yml
—
– hosts: sap_hosts
become: true
roles:
– sap_prep
– sap_scc
11. run.sh
#!/bin/bash
set -e
cd terraform
terraform init
terraform apply -auto-approve
INVENTORY=$(terraform output -raw ansible_inventory)
cd ../ansible
echo “[sap_hosts]” > inventory.ini
echo “$INVENTORY” >> inventory.ini
ansible-playbook -i inventory.ini site.yml
Output (from ansible):
Outputs:
public_ip = “<PUBLIC_IP>”
PLAY [sap_hosts] *************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************
[WARNING]: Host ‘ec2-user@<PUBLIC_IP>’ is using the discovered Python interpreter at ‘/usr/bin/python3.13’, but future installation of another Python interpreter could cause a different interpreter to be discovered. See https://docs.ansible.com/ansible-core/2.19/reference_appendices/interpreter_discovery.html for more information.
[WARNING]: sftp transfer mechanism failed on [ec2-user@<PUBLIC_IP>]. Use ANSIBLE_DEBUG=1 to see detailed information
[WARNING]: scp transfer mechanism failed on [ec2-user@<PUBLIC_IP>]. Use ANSIBLE_DEBUG=1 to see detailed information
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Install base packages] **************************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Start chronyd] **********************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Refresh SUSE repos] *****************************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Install Java 17 (OpenJDK)] **********************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Verify Java installation] ***********************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Ensure sccadm group exists] **********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Ensure sccadm user exists] ***********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Install prerequisites] ***************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Create installer directory] **********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Upload SCC ZIP (2.16.2)] *************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Extract SCC ZIP] *********************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Find SCC RPM inside extracted ZIP] ***************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Fail if SCC RPM not found] ***********************************************************************************
skipping: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Install SCC RPM with zypper] *********************************************************************************
changed: [ec
12. Once the SAP Cloud Connector service has started on your SUSE instance, open the administration UI in your browser.
https://<YOUR_PUBLIC_IP>:8443
From here you can change the default password and connect the SCC up to BTP / on-prem etc.
13. run_destroy.sh
#!/bin/bash
set -e
cd terraform
terraform destroy -auto-approve
cd ..
echo “# destroyed” > ansible/inventory.ini
Conclusion
Fully automated provisioning and configuration of SAP Cloud Connector on SLES using Terraform and Ansible, with JVM tuning for AWS Free Tier.
I’ve spent a bit of time experimenting with Cloud Connectors recently and wanted a faster, cleaner way to spin one up without all the usual hassle. In this post, I build on the earlier SCC and Ansible write-ups and bring everything together into a single workflow. We’ll automate the entire deployment using Terraform for provisioning and Ansible for configuration, resulting in a fully working SCC with minimal manual effort.This guide provides a fully working, fully automated setup using:Terraform for provisioning the EC2 instanceAnsible for OS prep and SCC installationHeap tuning via props.ini for stable SCC operation1. Directory layoutsap-lab/
├── run.sh
├── run_destroy.sh
│
├── terraform/
│ ├── main.tf
│ ├── variables.tf
│ ├── terraform.tfvars
│ └── <KEYPAIR_NAME>.pub
│
└── ansible/
├── site.yml
├── inventory.ini
├── ansible.cfg
└── roles/
├── sap_prep/
│ └── tasks/main.yml
└── sap_scc/
├── defaults/main.yml
├── tasks/main.yml
└── templates/scc_daemon.service.j22. Terraform: main.tfterraform {
required_version = “>= 1.5”
required_providers {
aws = {
source = “hashicorp/aws”
version = “~> 5.0”
}
}
}
provider “aws” {
region = var.region
}
resource “aws_security_group” “sap_scc_sg” {
name = “sap-scc-sg”
description = “Allow SCC UI and SSH”
vpc_id = var.vpc_id
ingress {
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
ingress {
from_port = 8443
to_port = 8443
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}
}
resource “aws_instance” “sap_scc” {
ami = var.sles_ami
instance_type = “t2.micro”
key_name = var.keypair_name
subnet_id = var.subnet_id
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.sap_scc_sg.id]
tags = {
Name = “SAP-LAB-SCC”
}
}
output “ansible_inventory” {
value = “sap_host ansible_host=${aws_instance.sap_scc.public_ip} ansible_user=ec2-user ansible_ssh_private_key_file=../terraform/${var.private_key} ansible_ssh_common_args=’-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'”
}3. Terraform Variables (variables.tf)variable “region” {}
variable “vpc_id” {}
variable “subnet_id” {}
variable “keypair_name” {}
variable “private_key” {}
variable “sles_ami” {}4. terraform.tfvarsregion = “us-east-2”
vpc_id = “vpc-xxxxxxxxxxxxxxxx”
subnet_id = “subnet-xxxxxxxxxxxx”
keypair_name = “my-keypair”
private_key = “my-keypair.pem”
sles_ami = “ami-xxxxxxxxxxxxxxxx”5. Ansible config (ansible.cfg)[defaults]
host_key_checking = False
retry_files_enabled = False6. Role: OS Preparation (sap_prep/tasks/main.yml)—
– name: Install prerequisites
zypper:
name:
– wget
– net-tools
– chrony
– unzip
– curl
state: present
– name: Ensure chronyd is running
service:
name: chronyd
state: started
enabled: yes
– name: Set vm.swappiness
ansible.posix.sysctl:
name: vm.swappiness
value: “10”
state: present
reload: yes7. SCC Role Defaults (sap_scc/defaults/main.yml)—
scc_version: “2.16.2”
scc_file: “sapcc-{{ scc_version }}-linux-x64.zip”
scc_install_dir: /opt/sap/scc
scc_user: sccadm
scc_group: sccadm
scc_jvm_xms: “256m”
scc_jvm_xmx: “512m”
scc_service_name: scc_daemon8. SCC Installation Tasks (sap_scc/tasks/main.yml)—
– name: Ensure sccadm group exists
group:
name: “{{ scc_group }}”
system: yes
– name: Ensure sccadm user exists
user:
name: “{{ scc_user }}”
group: “{{ scc_group }}”
shell: /sbin/nologin
system: yes
– name: Install prerequisites
become: yes
zypper:
name:
– unzip
– curl
– java-17-openjdk-headless
state: present
– name: Create installer directory
file:
path: /tmp/scc-installer
state: directory
– name: Upload SCC ZIP (2.16.2)
copy:
src: sapcc-2.16.2-linux-x64.zip
dest: /tmp/scc-installer/sapcc.zip
– name: Extract SCC ZIP
unarchive:
src: /tmp/scc-installer/sapcc.zip
dest: /tmp/scc-installer
remote_src: yes
– name: Locate SCC RPM
find:
paths: /tmp/scc-installer
patterns: “com.sap.scc-ui-*.rpm”
register: rpm_file
– name: Fail if SCC RPM not found
fail:
msg: “SCC RPM not found.”
when: rpm_file.matched == 0
– name: Install SCC RPM
become: yes
zypper:
name: “{{ rpm_file.files[0].path }}”
disable_gpg_check: yes
state: present
# Heap tuning
– name: Tune Xms
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘-Xms[0-9]+m’
replace: “-Xms{{ scc_jvm_xms }}”
– name: Tune Xmx
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘-Xmx[0-9]+m’
replace: “-Xmx{{ scc_jvm_xmx }}”
– name: Tune NewSize
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘NewSize=[0-9]+m’
replace: ‘NewSize=256m’
– name: Tune MaxNewSize
become: yes
replace:
path: /opt/sap/scc/props.ini
regexp: ‘MaxNewSize=[0-9]+m’
replace: ‘MaxNewSize=256m’
– name: Enable SCC daemon
become: yes
systemd:
name: “{{ scc_service_name }}”
enabled: yes
– name: Start SCC daemon
become: yes
systemd:
name: “{{ scc_service_name }}”
state: restarted9. Systemd Template (scc_daemon.service.j2)[Unit]
Description=SAP Cloud Connector
After=network.target
[Service]
Type=forking
User={{ scc_user }}
Group={{ scc_group }}
ExecStart=/opt/sap/scc/go.sh -start
ExecStop=/opt/sap/scc/go.sh -stop
Restart=on-failure
[Install]
WantedBy=multi-user.target10. site.yml—
– hosts: sap_hosts
become: true
roles:
– sap_prep
– sap_scc11. run.sh#!/bin/bash
set -e
cd terraform
terraform init
terraform apply -auto-approve
INVENTORY=$(terraform output -raw ansible_inventory)
cd ../ansible
echo “[sap_hosts]” > inventory.ini
echo “$INVENTORY” >> inventory.ini
ansible-playbook -i inventory.ini site.ymlOutput (from ansible):Outputs:
public_ip = “<PUBLIC_IP>”
PLAY [sap_hosts] *************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************
[WARNING]: Host ‘ec2-user@<PUBLIC_IP>’ is using the discovered Python interpreter at ‘/usr/bin/python3.13’, but future installation of another Python interpreter could cause a different interpreter to be discovered. See https://docs.ansible.com/ansible-core/2.19/reference_appendices/interpreter_discovery.html for more information.
[WARNING]: sftp transfer mechanism failed on [ec2-user@<PUBLIC_IP>]. Use ANSIBLE_DEBUG=1 to see detailed information
[WARNING]: scp transfer mechanism failed on [ec2-user@<PUBLIC_IP>]. Use ANSIBLE_DEBUG=1 to see detailed information
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Install base packages] **************************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Start chronyd] **********************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Refresh SUSE repos] *****************************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Install Java 17 (OpenJDK)] **********************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_prep : Verify Java installation] ***********************************************************************************
changed: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Ensure sccadm group exists] **********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Ensure sccadm user exists] ***********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Install prerequisites] ***************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Create installer directory] **********************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Upload SCC ZIP (2.16.2)] *************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Extract SCC ZIP] *********************************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Find SCC RPM inside extracted ZIP] ***************************************************************************
ok: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Fail if SCC RPM not found] ***********************************************************************************
skipping: [ec2-user@<PUBLIC_IP>]
TASK [sap_scc : Install SCC RPM with zypper] *********************************************************************************
changed: [ec12. Once the SAP Cloud Connector service has started on your SUSE instance, open the administration UI in your browser.https://<YOUR_PUBLIC_IP>:8443 From here you can change the default password and connect the SCC up to BTP / on-prem etc.13. run_destroy.sh#!/bin/bash
set -e
cd terraform
terraform destroy -auto-approve
cd ..
echo “# destroyed” > ansible/inventory.iniConclusionFully automated provisioning and configuration of SAP Cloud Connector on SLES using Terraform and Ansible, with JVM tuning for AWS Free Tier. Read More Technology Blog Posts by Members articles
#SAP
#SAPTechnologyblog