Infrastructure as Code (IaC)#
| Original Author | Provodin Grigory |
| Last checked by | |
| Status | Done |
| Last Updated | 19.06.2025 |
Requirements#
General#
-
Install Terraform: Link
-
Install Python, if not installed: Link
-
Create CSC account, if not created and remember the password: Link
-
Create the cPouta account, if not created: Link
Note: Follow only the first five steps, stopping before the
SSH Key Pairssection -
It is recommended to follow this guide after you have already tried deploying cPouta VMs manually
-
Read an intro to IaC: Link
CSC#
- Floating IPs: Your environment should not have any floating IPs assigned to machines or allocated at all.
The Overview section on the cPouta dashboard should show zero IPs allocated:

- Volumes: You should have at least 2 free volume spaces available. Verify in the Overview section of your dashboard:

- Virtual Resources: You need sufficient virtual resources to accommodate two VMs with
standard.mediumflavor.Required total: 6 VCPUs and 7.8 GB RAM. Verify in the Overview section of your dashboard:

Prerequisites#
Commands vs Script#
For almost every action in this guide, you have two options:
-
Run individual commands - Choose this option if you want to learn more about each step.
-
Use the provided script - Choose this for a faster and easier deployment.
Note: The script is written in Bash and works well with Linux and Mac but not with Windows unless you have Windows Subsystem for Linux (WSL) installed.
To make the script executable, run:
Cloning the Repository and Installing Dependencies#
-
Clone the repository and navigate to the project directory (from this point on all of the commands in this guide will be executed from the root directory e.g.
microk8s-automation): -
Create a Python virtual environment:
-
Install dependencies:
Note: When you're done using this virtual environment, deactivate it with the command
deactivate.For instructions for Windows and more information, refer to this Python venv guide.
Setting Up cPouta Access#
-
Open the cPouta dashboard.
-
Navigate to
API Accessin the dashboard.
-
Click on the
Download OpenStack RC Filedropdown menu, then select theOpenStack RC Filebutton.Important: Keep your RC file secure as it contains credentials for your project.

-
Source the RC file. You'll be prompted for the password you obtained during CSC account registration.
Note: Authentication will only work in the terminal where you sourced the file. If you want to use it in a new terminal session, you will need to source it again.
-
Test your connection by running OpenStack commands:
You can run this command:
* When successfully connected:
``` (.env) ➜ openstack router list +--------------------------------------+------------------------+--------+-------+----------------------------------+ | ID | Name | Status | State | Project | +--------------------------------------+------------------------+--------+-------+----------------------------------+ | 4ba41af4-a69d-440e-90f7-543688c8633a | project_xxxxxxx-router | ACTIVE | UP | 4d8ca737497f4a50bc7098b1df465dbf | +--------------------------------------+------------------------+--------+-------+----------------------------------+ ```* If you're not connected, you'll see:
``` (.env) ➜ openstack router list Missing value auth-url required for auth plugin password Could not clean up: 'ClientManager' object has no attribute 'session' ```
Importing the Rocky Linux Image#
This guide requires a virtual machine image that is not available by default on CSC. Choose one of the following methods to import it:
Option 1: Manual#
Follow this guide until the section Installing PrestaShop on Rocky Linux 9.
Important: Use the image name
Rocky-9.5instead ofRocky Linux 9as this naming convention is used in the Terraform and Heat configurations.
Option 2: Manual (CLI)#
-
Download the image from the website and save it in the
rocky-imagedirectory: -
Import the image to CSC:
Option 3: Script#
Run the script from the project's root directory:
Generating SSH Key Pairs#
You need to generate two key pairs for accessing your virtual machines.
Note: By default, SSH private keys are typically given permissions of
400(read-only by owner). In this guide, private keys are given read+write permissions (600) to allow overwriting the same file for multiple deployments. If you plan on doing only one deployment, you can change the permissions to400.The keys will be stored in the
keys/directory of this project rather than the standard/home/user/.sshlocation for simplicity.
Option 1: Manual (CLI)#
-
Create
keysdirectory: -
Generate two key pairs without passphrases:
-
Set appropriate permissions for private keys:
-
Set appropriate permissions for public keys:
-
Set appropriate permissions for the directory storing keys:
Option 2: Script#
Run the script from the project's root directory:
Customizing Key Locations (Optional)#
If you want to store your keys in a different location or use different names, you need to update the following files:
-
Ansible configuration (Private keys) - Edit
ansible/inventory.ymllines 5 and 11: -
Heat configuration (Public keys) - Edit
heat/main.yamllines 99 and 105: -
Terraform configuration (Public keys) - Edit
terraform/main.tflines 41 and 46:
Retrieving Network IDs#
You need to retrieve your cPouta project's public and private network IDs as they will be used by both Terraform and Heat to configure network resources.
Option 1: Manual (CLI)#
-
Get the public network ID:
-
Get the private network ID:
Option 2: Script#
Run the script from the project's root directory:
Updating Terraform and Heat Variable Files#
Update the following files with the network IDs you retrieved:
Note: Terraform uses only the private ID, while Heat requires both private and public.
-
Terraform - Edit
terraform/default-vars.tfvars: -
Heat - Edit
heat/default-vars.yaml:
How to navigate this guide?#
Once you've completed the prerequisites, you have flexibility in how you follow this guide:
- Infrastructure Only: You can deploy just the infrastructure using either Terraform or Heat without running Ansible. This creates the virtual machines and network resources.
- Complete Deployment: Deploy the infrastructure using either Terraform or Heat, then install PrestaShop with Ansible. For more practice, you can try deploying with one method (e.g., Terraform), destroy the infrastructure, then redeploy using the alternative method (e.g., Heat) then deploy PrestaShop with Ansible.
Important: Regardless of which deployment method you choose, ensure that your infrastructure is properly set up before running the Ansible playbook for PrestaShop installation.
Terraform#
Terraform is one of the most popular IaC tools on the market, adopted by many organizations for infrastructure deployment. Its features include:
- Cloud Compatibility: Works with all major cloud platforms including AWS, Azure, GCP, and others.
- CI/CD Integration: Easily integrates with continuous integration and delivery pipelines like GitLab CI/CD.
- Configuration Language: Uses HashiCorp Configuration Language (HCL), which has a flexible syntax. Modern IDEs like VS Code provide intellisense and code completion for HCL, offering a better configuration experience compared to many other IaC tools.
- Declarative Approach: You specify the desired end state, and Terraform determines how to achieve it.
Understanding Terraform State and File Structure#
Terraform maintains a record of your managed infrastructure and configurations in state files. These files are crucial for Terraform's operation:
- State files track what infrastructure exists and its current configuration.
- State files are generated with the first
applyin the project and updated during operations likeapplyanddestroy. - Do not modify or delete these files while having your infrastructure controlled by Terraform as you will lose control.
Terraform file structure (after running terraform apply):
terraform/
├── .terraform # Directory containing plugins and modules (e.g. openstack module)
│ └── ---stripped---
├── .terraform.lock.hcl # Dependency lock file
├── default-vars.tfvars # Variables (default values, can be also declared in variables.tf)
├── main.tf # Main file with all resource declaration (e.g VMs and security groups)
├── output.tf # Output that will be shown after deployment (e.g floating ips)
├── provider.tf # Declaration of provider (e.g. openstack)
├── terraform.tfstate # Current state file
├── terraform.tfstate.backup # Backup state file
└── variables.tf # Declaration of variables (name and type)
Deploying Infrastructure with Terraform#
To deploy your infrastructure with Terraform, do:
Option 1: Manual (CLI)#
terraform -chdir=terraform/ init
terraform -chdir=terraform/ plan -var-file="default-vars.tfvars" -out=infra
terraform -chdir=terraform/ apply infra
- The
initcommand initializes the Terraform working directory and downloads providers (OpenStack in case of this configuration) - The
plancommand creates an execution plan - The
applycommand executes the plan file to provision the infrastructure
Option 2: Script#
Run the script from the project's root directory:
If the Terraform deployment is successful, you'll receive an output with two floating IPs for your Ubuntu and Rocky VMs. Save these IPs as you'll need them later for Ansible configuration.
Deploy PrestaShop (Optional)#
At this point, you can deploy PrestaShop with Ansible.
Updating Infrastructure with Terraform (Optional)#
You can modify your existing infrastructure by updating the Terraform configuration files.
Note: It is not recommended to use machines with
standard.smallflavor as they may not handle Ansible, MicroK8s, and PrestaShop.
To update your infrastructure:
-
Edit the
terraform/default-vars.tfvarsfile to make your desired changes.For example, to add new security group ports and change instance flavors:
Before:
ubuntu_security_group_ports = [22, 80, 443] rocky_security_group_ports = [22, 80, 443] ubuntu_instance = "standard.medium" rocky_instance = "standard.medium"After:
-
Apply your changes using the same commands as deployment:
Option 1: Manual (CLI)
terraform -chdir=terraform/ plan -var-file="default-vars.tfvars" -out=infra terraform -chdir=terraform/ apply infraOption 2: Script
Run the script from the project's root directory:
Destroying Infrastructure with Terraform#
When you no longer need your infrastructure, you can destroy all resources created by Terraform:
Option 1: Manual (CLI)#
Option 2: Script#
Run the script from the project's root directory:
You will be prompted to confirm the destruction. Type "yes" if you want to proceed.
Warning: This will permanently delete all resources managed by Terraform in this project.
Heat#
Heat is a native OpenStack IaC tool, the platform that CSC cloud is built on. Its features include:
- Template-based: Uses YAML-based HOT (Heat Orchestration Templates) to define infrastructure resources.
- OpenStack Integration: As a native OpenStack service, it provides more control over the OpenStack resources than other IaC tools.
- Stack Management: Organizes resources into "stacks" that can be created, updated, and deleted as a single unit. The stack is server-side, meaning all orchestration logic runs on the OpenStack platform rather than your local machine. Moreover, the stack can be managed via a dashboard.
- Declarative Approach: You specify the desired end state, and Heat orchestration engine determines how to achieve it.
Deploying Infrastructure with Heat#
Option 1: Manual (CLI)#
To deploy your infrastructure using Heat:
-
First, validate your template to ensure it's correctly formatted:
-
Create the stack using your template and environment file:
-
Wait for the stack to be deployed (this typically takes a minute or two).
-
Verify that your stack has been successfully created:
A status of
CREATE_COMPLETEindicates that your stack was deployed successfully. -
Retrieve the floating IPs assigned to your virtual machines:
Option 2: Script#
Run the script from the project's root directory:
Heat Dashboard#
When you deploy with Heat you get to use the dashboard for managing your deployment.
-
On the cPouta dashboard, go to
Orchestration-->Stacks. You will see avm-stack, click on it.
-
On this dashboard you will see some generic information about your deployment. The network topology, stack parameters, the resources that were created and their states, the template that was used to create this stack. If the stack creation fails, you will see an error message describing what went wrong. Finally, you can delete the stack from this dashboard if you wish.

Deploy PrestaShop (Optional)#
At this point, you can deploy PrestaShop with Ansible.
Updating Infrastructure with Heat (Optional)#
You can modify your existing infrastructure by updating the Heat configuration files.
Note: It is not recommended to use machines with
standard.smallflavor as they may not handle Ansible, MicroK8s, and PrestaShop.
-
Edit the
heat/default-vars.yamlfile to make your desired changes.For example, to add new security group ports and change instance flavors:
Before:
parameter_defaults: ubuntu_security_group_ports: "22,80,443" rocky_security_group_ports: "22,80,443" ubuntu_instance: standard.medium rocky_instance: standard.mediumAfter:
-
Apply the changes to your existing stack:
#### Option 1: Manual (CLI)
#### Option 2: Script
Run the script from the project's root directory:
-
Monitor the update progress:
A status of
UPDATE_COMPLETEindicates that your stack has been successfully updated.
Destroying Infrastructure with Heat#
When you no longer need your infrastructure, you can delete the entire stack:
Option 1: Manual (CLI)#
Option 2: Script#
Run the script from the project's root directory:
This will remove all resources that were created as part of the stack. You can confirm that the stack has been deleted by running:
Your vm-stack should no longer appear in the list once the deletion is complete.
Warning: Deleting a stack removes all its resources permanently.
Ansible#
Ansible is a popular IaC tool used for cloud and server configurations. It automates many of the manual tasks, think of it as a fancier way of running scripts on a server. If you have done Data Networks course, think that most of the stuff you did there could be automated with Ansible. Its features include:
- Agentless Architecture: Requires no software installation on managed nodes (devices being managed by Ansible e.g. VMs), using only SSH connections and Python to deploy configurations.
- Idempotent Operations: When configured correctly, Ansible ensures that applying the same configuration multiple times produces consistent results without side effects.
- Parallel Execution: Can run the same or different configurations on many servers simultaneously, making large-scale deployments efficient.
- YAML-Based Playbooks: Uses human-readable YAML syntax to define automation tasks.
Customizing PrestaShop Admin Settings (Optional)#
By default, this PrestaShop deployment uses generic admin credentials and folder name. You can customize these settings by modifying the Ansible playbook at ansible/microk8s-deployment.yml.
To set your own admin folder name, email, and password, add these three parameters to the helm command:
--set prestashop.env.psFolderAdmin="<your-folder>" \
--set prestashop.env.adminMail="<student@jamk.fi>" \
--set prestashop.env.adminPasswd="<your-password>"
Example Modification:
Before:
- name: Deploy PrestaShop using helm chart
ansible.builtin.shell: |
microk8s helm install presta-helm prestashop \
--set prestashop.env.psDomain="{{ domain_result.stdout }}" \
--set prestashop.ingress.enabled=true \
--set prestashop.ingress.letsencrypt.isProd=true \
--set common.persistence.enabled=true
After:
- name: Deploy PrestaShop using helm chart
ansible.builtin.shell: |
microk8s helm install presta-helm prestashop \
--set prestashop.env.psDomain="{{ domain_result.stdout }}" \
--set prestashop.ingress.enabled=true \
--set prestashop.ingress.letsencrypt.isProd=true \
--set common.persistence.enabled=true \
--set prestashop.env.psFolderAdmin="adminfolder" \
--set prestashop.env.adminMail="student@jamk.fi" \
--set prestashop.env.adminPasswd="superstrongpassword***"
Deploy PrestaShop#
If you want to learn more about how PrestaShop was deployed on the MicroK8s, look at this guide:
-
Setting up an inventory file
Before running the playbook, you will need to modify the inventory file located at
ansible/inventory.ymlby adding floating IPs you retrieved from either Heat or Terraform deployment.Example Modification:
Before:
dev: hosts: ubuntu: ansible_host: ansible_ssh_private_key_file: ./keys/ubuntu_key ansible_user: ubuntu ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ConnectionAttempts=20 -o ConnectTimeout=60' rocky: ansible_host: ansible_ssh_private_key_file: ./keys/rocky_key ansible_user: rocky ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ConnectionAttempts=20 -o ConnectTimeout=60'After:
dev: hosts: ubuntu: ansible_host: 89.96.183.55 ansible_ssh_private_key_file: ./keys/ubuntu_key ansible_user: ubuntu ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ConnectionAttempts=20 -o ConnectTimeout=60' rocky: ansible_host: 250.102.192.186 ansible_ssh_private_key_file: ./keys/rocky_key ansible_user: rocky ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ConnectionAttempts=20 -o ConnectTimeout=60' -
Executing the playbook:
Option 1: Manual (CLI)
Option 2: Script
Run the script from the project's root directory:
Note: The deployment process can take several minutes to complete.
Accessing the PrestaShop Website#
After the deployment completes successfully, you can access the PrestaShop website using domains provided in the Ansible playbook output.

Default credentials:
- Link to the website:
https://fip-AAA-BBB-CCC-DDD.kaj.poutavm.fi/ - Link to the admin dashboard:
https://fip-AAA-BBB-CCC-DDD.kaj.poutavm.fi/admin228/ - Admin email:
testuser@mail.com - Admin password:
ReAlPaSsWoRd759***
Accessing Your Virtual Machines#
You can SSH into your virtual machines to check the status of the deployment:
SSH to Ubuntu VM#
SSH to Rocky VM#
Resolving SSH Host Key Issues#
If you've deployed multiple times with the same floating IP, you might encounter a "REMOTE HOST IDENTIFICATION HAS CHANGED" error:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
To resolve this, run the command suggested in the error message:
ssh-keygen -f '/home/user/.ssh/known_hosts' -R '86.50.229.170' # Replace with the IP address and path in your error message
Checking PrestaShop Deployment Status#
Once connected to either VM, you can check the status of the PrestaShop deployment:
The PrestaShop application is being deployed from scratch, so it will take some time to become accessible. When the deployment is complete, you should see logs indicating that the application is ready.

Cleaning Up Resources#
When you're done with your infrastructure, delete all of your resources:
Terraform#
Destroying Infrastructure with Terraform
Heat#
Destroying Infrastructure with Heat
Warning: These commands will permanently delete all resources created in your project.