---
title: "Create a cloud server with a direct public IP address using Terraform"
sidebar_label: "Create a cloud server with a direct public IP address"
sidebar_position: 4
description: "How to create a cloud server with a direct public IP address"
---

import Formbricks from '@theme/MDXComponents/Formbricks'
import ConfigureProviders from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/configure-providers.mdx'
import ConfigureProvidersConfig from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/configure-providers-config.mdx'
import AddPublicSsh from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/add-public-ssh-key.mdx'
import GetImage from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/get-image.mdx'
import CreateBootVolume from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/create-boot-volume.mdx'
import CreateFixedServerBootNetwork from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/create-fixed-server-with-boot-network-volume.mdx'
import CreateResourcesAlert from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/create-resources-alert.mdx'
import GetIp from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-networks/get-ip.mdx'

# Create a cloud server with a direct public IP address using Terraform

<CreateResourcesAlert />

<br />

1. Optional: [configure providers](#configure-providers).
2. [Add a public SSH key](#add-public-ssh-key).
3. [Create a security group](#create-security-group).
4. [Create a port with a direct public IP address](#create-port).
5. [Get an image](#get-image).
6. [Create a bootable network volume](#create-boot-volume).
7. [Create a cloud server](#create-server).
8. [Get the cloud server IP address](#get-ip).

## Configuration files \{#config}

<details>
  <summary>Example file for configuring providers</summary>

  <ConfigureProvidersConfig />
</details>

<details>
  <summary>Example file for creating a cloud server with a direct public IP address</summary>

  ```hcl
  resource "selectel_vpc_keypair_v2" "keypair_1" {
    name       = "keypair"
    public_key = file("~/.ssh/id_rsa.pub")
    user_id    = selectel_iam_serviceuser_v1.serviceuser_1.id
  }

  resource "openstack_networking_secgroup_v2" "secgroup_1" {
    name = "security_group"
  }

  resource "openstack_networking_secgroup_rule_v2" "ssh_ingress" {
    direction         = "ingress"
    ethertype         = "IPv4"
    protocol          = "tcp"
    port_range_min    = 22
    port_range_max    = 22
    remote_ip_prefix  = "0.0.0.0/0"
    security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
  }

  resource "openstack_networking_secgroup_rule_v2" "icmp_ingress" {
    direction         = "ingress"
    ethertype         = "IPv4"
    protocol          = "icmp"
    remote_ip_prefix  = "0.0.0.0/0"
    security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
  }

  resource "selectel_vpc_public_port_v1" "public_port_1" {
    name               = "public_port"
    security_group_ids = [openstack_networking_secgroup_v2.secgroup_1.id] 
  }

  data "openstack_images_image_v2" "image_1" {
    name        = "Ubuntu 20.04 LTS 64-bit"
    most_recent = true
    visibility  = "public"
  }

  resource "openstack_blockstorage_volume_v3" "volume_1" {
    name                 = "boot-volume-for-server"
    size                 = "5"
    image_id             = data.openstack_images_image_v2.image_1.id
    volume_type          = "fast.ru-6a"
    availability_zone    = "ru-6a"
    enable_online_resize = true

    lifecycle {
      ignore_changes = [image_id]
    }

  }

  resource "openstack_compute_instance_v2" "server_1" {
    name              = "server"
    flavor_id         = "1054"
    key_pair          = selectel_vpc_keypair_v2.keypair_1.name
    availability_zone = "ru-6a"

    network {
      port = selectel_vpc_public_port_v1.public_port_1.id
      uuid = selectel_vpc_public_port_v1.public_port_1.network_id
      name = "network"
    }

    lifecycle {
      ignore_changes = [image_id, availability_zone]
    }

    block_device {
      uuid             = openstack_blockstorage_volume_v3.volume_1.id
      source_type      = "volume"
      destination_type = "volume"
      boot_index       = 0
    }

    vendor_options {
      ignore_resize_confirmation = true
    }
  }

  output "public_ip_address" {
    value = selectel_vpc_public_port_v1.public_port_1.ip_address
  }
  ```
</details>

## 1. Optional: configure providers \{#configure-providers}

If you [configured the providers](/terraform/configure-terraform-environment/#configure-providers) Selectel and OpenStack, skip this step.

<ConfigureProviders />

## 2. Add a public SSH key \{#add-public-ssh-key}

<AddPublicSsh />

## 3. Create a security group \{#create-security-group}

```hcl
resource "openstack_networking_secgroup_v2" "secgroup_1" {
  name = "security_group"
}

resource "openstack_networking_secgroup_rule_v2" "ssh_ingress" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
}

resource "openstack_networking_secgroup_rule_v2" "icmp_ingress" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "icmp"
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
}
```

See detailed descriptions of the resources:

* [openstack\_networking\_secgroup\_v2](/terraform/openstack-provider-reference/networking-neutron/resources/openstack_networking_secgroup_v2/);
* [openstack\_networking\_secgroup\_rule\_v2](/terraform/openstack-provider-reference/networking-neutron/resources/openstack_networking_secgroup_rule_v2/).

## 4. Create a port with a direct public IP address \{#create-port}

```hcl
resource "selectel_vpc_public_port_v1" "public_port_1" {
  name               = "public_port"
  security_group_ids = openstack_networking_secgroup_v2.secgroup_1.id

}
```

See a detailed description of the resource [selectel\_vpc\_public\_port\_v1](/terraform/selectel-provider-reference/resources/vpc_public_port_v1/).

## 5. Get an image \{#get-image}

<GetImage />

## 6. Create a bootable network volume \{#create-boot-volume}

<CreateBootVolume />

## 7. Create a cloud server \{#create-server}

```hcl
resource "openstack_compute_instance_v2" "server_1" {
  name              = "server"
  flavor_id         = "1054"
  key_pair          = selectel_vpc_keypair_v2.keypair_1.name
  availability_zone = "ru-6a"

  network {
    port = selectel_vpc_public_port_v1.public_port_1.id
    uuid = selectel_vpc_public_port_v1.public_port_1.network_id
    name = "network"
  }

  lifecycle {
    ignore_changes = [image_id, availability_zone]
  }

  block_device {
    uuid             = openstack_blockstorage_volume_v3.volume_1.id
    source_type      = "volume"
    destination_type = "volume"
    boot_index       = 0
  }

  vendor_options {
    ignore_resize_confirmation = true
  }
}
```

Where:

* `flavor_id` — flavor ID. Flavors correspond to [cloud server configurations](/cloud-servers/create/configurations/) and determine the number of vCPUs, RAM, and the server's local disk size (optional). For example, `1054` is an ID for creating a server with a fixed configuration from the Standard line with 4 vCPUs, 8 GB RAM with dedicated cores in the ru-6 pool. You can view the list of available flavors in the [List of fixed configuration flavors across all pools](/cloud-servers/create/configurations/#server-flavors-full-list) subsection of the [Cloud server configurations](/cloud-servers/create/configurations/);

* `availability_zone` — [pool segment](/infrastructure/locations/#pool) in which the cloud server will be created, for example `ru-6a`. You can view the list of available pool segments in the [Availability matrices](/infrastructure/product-availability-by-location/);

* in the `network:` block:

  * `name` — network name. You can specify any arbitrary value, as the network will be found by the parameter `uuid`.

See a detailed description of the resource [openstack\_compute\_instance\_v2](/terraform/openstack-provider-reference/compute-nova/resources/openstack_compute_instance_v2/).

## 8. Get the cloud server IP address \{#get-ip}

```hcl
output "public_ip_address" {
  value = selectel_vpc_public_port_v1.public_port_1.ip_address
}
```

<Formbricks />
