Skip to content

Create the first instance

In the previous page, we configured Terraform to be used with Infomaniak Public Cloud.
In this tutorial we will deploy a simple web server using Terraform.

Configure the key pair

In order to connect to our virtual servers, we must configure a SSH keypair.

If you have already generated a SSH keypair, this is the recommended way to add it to your Terraform configuration.

Edit your main.tf file and add the following resource :

main.tf
24
25
26
27
resource "openstack_compute_keypair_v2" "my_keypair" {
  name       = "my-keypair"
  public_key = "ssh-rsa ..." # TODO: changeme # (1)!
}
  1. 📝 You have to copy the entire public key on one line.

You may find additional information on the official documentation

To generate a new keypair using Terraform, Edit your main.tf file and add the following resource :

main.tf
24
25
26
resource "openstack_compute_keypair_v2" "my_keypair" {
  name = "my-keypair"  # TODO: changeme
}

Terraform will create a Public/Private Key Pair

Important Security Notice

The private key generated by this resource will be stored unencrypted in your Terraform state file.
Use of this resource for production deployments is not recommended.
Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run.

Configure the security group

By default, Infomaniak Public Cloud block all traffic for new instances. To allow traffic you must add rules in the default security group or create a new one.

In this tutorial we will create a new security group that will allows traffic on port 22 (SSH), 80 (HTTP) and 443 (HTTPS).

Open your main.tf and add the following resources :

main.tf
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Define the security group
resource "openstack_networking_secgroup_v2" "my_security_group" {
  name                 = "my_security_group"
  description          = "My neutron security group"
  # We want our security group to be fully managed by Terraform
  delete_default_rules = true # (1)!
}

# Add SSH rule to our security group
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}

# Allow HTTP
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh_http" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 80
  port_range_max    = 80
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}

# Allow HTTPs
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh_https" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 443
  port_range_max    = 443
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}
  1. ℹ When creating a security group, Openstack will automatically add default rules. This option remove the default rules.

You can find more information on the official documentation.

Create the instance

To launch a new instance, you will need the following information :

  • Image ID
  • Flavor Name
  • Network Name

These information can be retrieved using the Openstack Dashboard or by the Openstack CLI client.

Edit the main.tf file and add the following resource :

field name content example
instance_name Name of your instance web-server
image_name Name of the image you want to use Debian 12 bookworm
network_name Name of the network where the VM will be ext-net1
flavor_name Name of the flavor you want to use a1-ram2-disk80-perf1
keypair_name Name of the keypair define previously my_keypair
security_group_name Name of the security group define previously my_security_group
main.tf
73
74
75
76
77
78
79
80
81
82
83
84
# Create a web server resource
resource "openstack_compute_instance_v2" "my_webserver" {
  name            = "web-server"
  image_name      = "Debian 12 bookworm"
  flavor_name     = "a1-ram2-disk80-perf1"
  key_pair        = openstack_compute_keypair_v2.my_keypair.name
  security_groups = [openstack_networking_secgroup_v2.my_security_group.name]

  network {
    name          = "ext-net1"
  }
}

You may find additional information about compute resource on the official documentation

Now, your configuration should be similar to this :

main.tf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Define required providers
terraform {
  # Ensure the use of a compatible Terraform version
  required_version = ">= 0.14.0"
  required_providers {
    # Define OpenStack terraform provider
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      # This make sure to only allow the rightmost version component to increment (only minor update).
      version = "~> 2.0.0"
    }
  }
}

# Configure the OpenStack Provider
provider "openstack" {
  auth_url    = "https://api.pub1.infomaniak.cloud/identity"
  region      = "dc3-a"
  user_name   = "PCU-XXXXXXX" # TODO: changeme
  tenant_name = "PCP-XXXXXXX" # TODO: changeme
  password    = "your_password" # TODO: changeme
}

resource "openstack_compute_keypair_v2" "my_keypair" {
  name       = "my-keypair"  # TODO: changeme
  public_key = "ssh-rsa ..." # TODO: changeme
}

# Define the security group
resource "openstack_networking_secgroup_v2" "my_security_group" {
  name                 = "my_security_group"
  description          = "My neutron security group"
  # We want our security group to be fully managed by Terraform
  delete_default_rules = true # Remove default rules generated by OpenStack
}

# Add SSH rule to our security group
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}

# Allow HTTP
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh_http" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 80
  port_range_max    = 80
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}

# Allow HTTPs
resource "openstack_networking_secgroup_rule_v2" "my_sg_ssh_https" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 443
  port_range_max    = 443
  remote_ip_prefix  = "0.0.0.0/0"
  # Link the rule to our security group
  security_group_id = openstack_networking_secgroup_v2.my_security_group.id
}

# Create a web server resource
resource "openstack_compute_instance_v2" "my_webserver" {
  name            = "web-server"
  image_name      = "Debian 12 bookworm"
  flavor_name     = "a1-ram2-disk80-perf1"
  key_pair        = openstack_compute_keypair_v2.my_keypair.name
  security_groups = [openstack_networking_secgroup_v2.my_security_group.name]

  network {
    name          = "ext-net1"
  }
}

Deploy the configuration

Now that our Terraform recipe is ready, we can send the configuration to the public cloud.

First, we have to initialize our project:

> shell
tofu init
> shell
terraform init

This will initialize the backend, plugins and modules (if you have any).

Then, we can validate our configuration :

> shell
tofu validate
> shell
terraform validate

You should see an output telling that Success! The configuration is valid..

Finally, we can send our configuration to the cloud:

> shell
tofu apply
> shell
terraform apply

This will preview the resources modifications.
When prompted, type yes to confirm the deployment.

> shell
Plan: 6 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  OpenTofu will perform the actions described above.
  Only 'yes' will be accepted to approve.

During the deployment you should obtain a result like this:

> shell
openstack_compute_keypair_v2.my_keypair: Creating...
openstack_networking_secgroup_v2.my_security_group: Creating...
openstack_compute_keypair_v2.my_keypair: Creation complete after 0s [id=my-keypair]
openstack_networking_secgroup_v2.my_security_group: Creation complete after 1s [id=b061b537-dfb2-4f15-b069-77000a7bb7af]
openstack_networking_secgroup_rule_v2.my_sg_ssh: Creating...
openstack_networking_secgroup_rule_v2.my_sg_ssh_https: Creating...
openstack_networking_secgroup_rule_v2.my_sg_ssh_http: Creating...
openstack_compute_instance_v2.my_webserver: Creating...
openstack_networking_secgroup_rule_v2.my_sg_ssh: Creation complete after 0s [id=ca74a2e0-cd1c-494f-98ae-188c842628ff]
openstack_networking_secgroup_rule_v2.my_sg_ssh_http: Creation complete after 0s [id=926c9ec5-37a7-4d97-9f44-6ad2703250be]
openstack_networking_secgroup_rule_v2.my_sg_ssh_https: Creation complete after 0s [id=18111495-61fa-4cf0-88a7-0f1e36342c72]
openstack_compute_instance_v2.my_webserver: Still creating... [10s elapsed]
openstack_compute_instance_v2.my_webserver: Still creating... [20s elapsed]
openstack_compute_instance_v2.my_webserver: Creation complete after 22s [id=6c4179a9-d834-41bb-9926-a28911965dde]

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.

Success

You have now a working instance successfully deployed with Terrafom on Infomaniak Public Cloud.