Terraform
Build infrastructure
With Terraform installed, you are ready to create infrastructure for the first time.
In this tutorial, you will deploy a Virtual Cloud Network (VCN) on Oracle Cloud Infrastructure (OCI) using Terraform. Other OCI resources need to deploy into a VCN.
Prerequisites
To follow this tutorial you will need:
- OCI Tenancy. Note your region, you will use it throughout the tutorial.
- The Terraform CLI installed.
- The OCI CLI installed.
Note
This tutorial will create resources in OCI. While VCNs do not incur a cost in OCI (in the always free tier or paid accounts), you should always be aware of the potential for incurring costs. We're not responsible for the charges you might incur.
Configure the OCI CLI from your terminal.
$ oci session authenticate
Enter a region by index or name(e.g.
1: ap-chiyoda-1, 2: ap-chuncheon-1, 3: ap-hyderabad-1, 4: ap-melbourne-1, 5: ap-mumbai-1,
6: ap-osaka-1, 7: ap-seoul-1, 8: ap-sydney-1, 9: ap-tokyo-1, 10: ca-montreal-1,
11: ca-toronto-1, 12: eu-amsterdam-1, 13: eu-frankfurt-1, 14: eu-zurich-1, 15: me-dubai-1,
16: me-jeddah-1, 17: sa-santiago-1, 18: sa-saopaulo-1, 19: uk-cardiff-1, 20: uk-gov-cardiff-1,
21: uk-gov-london-1, 22: uk-london-1, 23: us-ashburn-1, 24: us-gov-ashburn-1, 25: us-gov-chicago-1,
26: us-gov-phoenix-1, 27: us-langley-1, 28: us-luke-1, 29: us-phoenix-1, 30: us-sanjose-1):
Follow the prompts to enter the region where you have OCI tenancy. A browser window automatically opens and prompts you for your OCI user name and password. Enter them and click the "Sign In" button. Then return to your terminal. It displays a success message, which means that you have configured the OCI CLI with a default profile.
Completed browser authentication process!
Config written to: /Users/dos/.oci/config
Try out your newly created session credentials with the following example command:
oci iam region list --config-file /Users/dos/.oci/config --profile DEFAULT --auth security_token
Now Configure the OCI CLI with an additional named profile.
$ oci session authenticate
Enter a region by index or name(e.g.
1: ap-chiyoda-1, 2: ap-chuncheon-1, 3: ap-hyderabad-1, 4: ap-melbourne-1, 5: ap-mumbai-1,
6: ap-osaka-1, 7: ap-seoul-1, 8: ap-sydney-1, 9: ap-tokyo-1, 10: ca-montreal-1,
11: ca-toronto-1, 12: eu-amsterdam-1, 13: eu-frankfurt-1, 14: eu-zurich-1, 15: me-dubai-1,
16: me-jeddah-1, 17: sa-santiago-1, 18: sa-saopaulo-1, 19: uk-cardiff-1, 20: uk-gov-cardiff-1,
21: uk-gov-london-1, 22: uk-london-1, 23: us-ashburn-1, 24: us-gov-ashburn-1, 25: us-gov-chicago-1,
26: us-gov-phoenix-1, 27: us-langley-1, 28: us-luke-1, 29: us-phoenix-1, 30: us-sanjose-1):
Follow the prompts to enter the region where you have OCI tenancy. A browser window automatically opens and prompts you for your OCI user name and password. Enter them and click the "Sign In" button. Then return to your terminal. It displays a success message and prompts you for a profile name.
Completed browser authentication process!
Enter the name of the profile you would like to create:
Enter learn-terraform
for your profile name.
Enter the name of the profile you would like to create: learn-terraform
Config written to: /Users/<your-home-directory>/.oci/config
Try out your newly created session credentials with the following example command:
oci iam region list --config-file /Users/<your-home-directory>/.oci/config --profile learn-terraform --auth security_token
The output prints the location where the CLI has stored your token. Terraform will automatically detect the token later in the tutorial, and use the credentials there to create infrastructure. The token has a 1-hour Time To Live (TTL). If it expires, refresh it by providing the profile name.
$ oci session refresh --profile learn-terraform
Attempting to refresh token from https://auth.us-sanjose-1.oraclecloud.com/v1/authentication/refresh
Successfully refreshed token
Write configuration
The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. You will write your first configuration to define a single OCI VCN.
Each Terraform configuration must be in its own working directory. Create a directory for your configuration.
Make the learn-terraform-oci
directory.
$ mkdir learn-terraform-oci
Change to the learn-terraform-oci
directory.
$ cd learn-terraform-oci
Create a file to define your infrastructure.
$ touch main.tf
Open main.tf
in your text editor and paste in the configuration below.
terraform {
required_providers {
oci = {
source = "oracle/oci"
}
}
}
provider "oci" {
region = "us-sanjose-1"
auth = "SecurityToken"
config_file_profile = "learn-terraform"
}
resource "oci_core_vcn" "internal" {
dns_label = "internal"
cidr_block = "172.16.0.0/20"
compartment_id = "<your_compartment_OCID_here>"
display_name = "My internal VCN"
}
Customize the following values:
region
- value should match your OCI region.compartment_id
- value should match your "OCID" which you can get by clicking on the profile icon in the far top right of the OCI console and selecting "Tenancy: YourUsername" from the dropdown menu.
Save the customized file.
This is a complete configuration that you can deploy with Terraform. In the following sections, we will review each block of this configuration in more detail.
Terraform block
The terraform {}
block contains Terraform settings, including the required
providers Terraform will use to provision your infrastructure. For each provider, the
source
attribute defines an optional hostname, a namespace, and the provider
type. Terraform installs providers from the Terraform
Registry by default. In this example
configuration, the oci
provider's source is defined as oracle/oci
, which
is shorthand for registry.terraform.io/oracle/oci
.
You can also set a version constraint for each provider defined in the
required_providers
block. The version
attribute is optional, but we
recommend using it to constrain the provider version so that Terraform does not
install a version of the provider that does not work with your configuration. If
you do not specify a provider version, Terraform will automatically download the
most recent version during initialization.
To learn more, reference the provider source documentation.
Providers
The provider
block configures the specified provider, in this case oci
. A
provider is a plugin that Terraform uses to create and manage your resources.
The config_file_profile
attribute in the OCI provider block refers Terraform to the token credentials stored in the file that the OCI CLI created when you configured it. Never hard-code credentials or other secrets in your configuration files. Like other types of code, you may share and manage your Terraform configuration files using source control, so hard-coding secret values can expose them to attackers.
You can use multiple provider blocks in your Terraform configuration to manage resources from different providers. You can even use different providers together. For example, you could pass the IP address of an OCI instance to a monitoring resource from DataDog.
Resources
Use resource
blocks to define components of your infrastructure. A resource
might be a physical or virtual component such as a VCN, or it can be a
logical resource such as a Heroku application.
Resource blocks have two strings before the block: the resource type and the
resource name. In this example, the resource type is oci_core_vcn
and the name
is internal
. The prefix of the type maps to the name of the provider, in this
case, oci
. Together, the resource type and resource name form Terraform's unique ID
for the resource. For example, the ID for your VCN is oci_core_vcn.internal
.
Resource blocks contain arguments which you use to configure the resource. The example configuration contains arguments that set the DNS label, the CIDR block for the VCN, your OCID, and the display name. The OCI provider documentation documents the required and optional arguments for each resource in the OCI provider.
Initialize the directory
When you create a new configuration — or check out an existing configuration
from version control — you need to initialize the directory with terraform init
.
Initializing a configuration directory downloads and installs the providers
defined in the configuration, which in this case is the oci
provider.
Initialize the directory.
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of oracle/oci...
- Installing oracle/oci v5.7.0...
- Installed oracle/oci v5.7.0 (signed by a HashiCorp partner, key ID 1533A49284137CEB)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform downloads the oci
provider and installs it in a hidden
subdirectory of your current working directory, named .terraform
. The
terraform init
command prints out which version of the provider was installed.
Terraform also creates a lock file named .terraform.lock.hcl
which specifies the exact provider versions
used, so that you can control when you want to update the providers used for
your project.
Format and validate the configuration
We recommend using consistent formatting in all of your configuration files. The
terraform fmt
command automatically updates configurations in the current
directory for readability and consistency.
Format your configuration. Terraform will print out the names of the files it modified, if any. In this case, your configuration file was already formatted correctly, so Terraform won't return any file names.
$ terraform fmt
You can also make sure your configuration is syntactically valid and internally
consistent by using the terraform validate
command.
Validate your configuration. The example configuration provided above is valid, so Terraform will return a success message.
$ terraform validate
Success! The configuration is valid.
Create infrastructure
Apply the configuration now with the terraform apply
command. Terraform will
print output similar to what is shown below. We have truncated some of the
output to save space.
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# oci_core_vcn.internal will be created
+ resource "oci_core_vcn" "internal" {
+ byoipv6cidr_blocks = (known after apply)
+ cidr_block = "172.16.0.0/20"
+ cidr_blocks = (known after apply)
+ compartment_id = "ocid1.tenancy.oc1...."
+ default_dhcp_options_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_list_id = (known after apply)
+ defined_tags = (known after apply)
+ display_name = "My internal VCN"
+ dns_label = "internal"
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ ipv6cidr_blocks = (known after apply)
+ ipv6private_cidr_blocks = (known after apply)
+ is_ipv6enabled = (known after apply)
+ is_oracle_gua_allocation_enabled = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ vcn_domain_name = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Before it applies any changes, Terraform prints out the execution plan which describes the actions Terraform will take in order to change your infrastructure to match the configuration.
The output format is similar to the diff format generated by tools such as Git.
The output has a +
next to oci_core_vcn.internal
, meaning that Terraform will
create this resource. Beneath that, it shows the attributes that will be set.
When the value displayed is (known after apply)
, it means that the value won't
be known until the resource is created. For instance, OCI assigns its own ID
when it creates the VCN, so Terraform cannot know the value of the ID
attribute until you apply the change and the OCI provider returns that value
from the OCI API.
Terraform will now pause and wait for your approval before proceeding. If anything in the plan seems incorrect or dangerous, it is safe to abort here with no changes made to your infrastructure.
In this case the plan is acceptable, so type yes
at the confirmation prompt to
proceed. Executing the plan will take a few minutes since Terraform waits for
the VCN to become available.
Enter a value: yes
oci_core_vcn.internal: Creating...
oci_core_vcn.internal: Creation complete after 1s [id=ocid1.vcn.oc1.us-sanjose-1.amaaaaaapqqlmeyaklull6tpfms534aoijpjwpkzjo25rxqiqhadgdzodnua]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
You've now created infrastructure using Terraform! Visit the OCI console VCN page, select your compartment, and find your new VCN, listed as "My internal VCN".
Tip
Per the OCI resource block, your VCN was created in the
region you specified. Ensure that you are looking at the OCI console in this
region by checking the ?region=
query parameter in the URL.
Inspect state
When you applied your configuration, Terraform wrote data into a file called
terraform.tfstate
. Terraform stores the IDs and properties of the resources it
manages in this file, so that it can update or destroy those resources going
forward.
The Terraform state file is the only way Terraform can track which resources it manages, and often contains sensitive information, so you must store your state file securely and distribute it only to trusted team members who need to manage your infrastructure. In production, we recommend storing your state remotely with HCP Terraform or Terraform Enterprise. Terraform also supports several other remote backends you can use to store and manage your state.
Inspect the current state using terraform show
.
$ terraform show
# oci_core_vcn.internal:
resource "oci_core_vcn" "internal" {
cidr_block = "172.16.0.0/20"
cidr_blocks = [
"172.16.0.0/20",
]
compartment_id = "ocid1.tenancy.oc1...."
default_dhcp_options_id = "ocid1.dhcpoptions.oc1.us-sanjose-1.aaaaaaaa6odqyurw4mf7jmf3jy6ehtw6n32ohyogy4w5c43qoubgewyxr2va"
default_route_table_id = "ocid1.routetable.oc1.us-sanjose-1.aaaaaaaan3n6iazjfubarvwwtszl3v6gdzqvfoccdj555p2ujehbo4tlu7ma"
default_security_list_id = "ocid1.securitylist.oc1.us-sanjose-1.aaaaaaaant6vlu2y77pwwzjubmzg6czzvo2laii4h3p5d7w2nqcr4fey5gaa"
defined_tags = {
"Oracle-Tags.CreatedBy" = "oracleidentitycloudservice/redacted"
"Oracle-Tags.CreatedOn" = "2021-04-07T18:25:06.555Z"
}
display_name = "My internal VCN"
dns_label = "internal"
freeform_tags = {}
id = "ocid1.vcn.oc1.us-sanjose-1.amaaaaaapqqlmeyaklull6tpfms534aoijpjwpkzjo25rxqiqhadgdzodnua"
ipv6cidr_blocks = []
ipv6private_cidr_blocks = []
is_ipv6enabled = false
state = "AVAILABLE"
time_created = "2021-04-07 18:25:06.558 +0000 UTC"
vcn_domain_name = "internal.oraclevcn.com"
}
When Terraform created this VCN, it also gathered a lot of information about it from the OCI provider. These values can be referenced to configure other resources or outputs, which we discuss more later on in these tutorials.
Manually managing state
Terraform has a built-in command called terraform state
for advanced state
management. For example, you may want a list of the resources in your project's
state, which you can get by using the list
subcommand.
$ terraform state list
oci_core_vcn.internal
Next steps
Now that you have created your first infrastructure using Terraform, continue to the next tutorial to modify your infrastructure.
For more detail on the concepts we used in this tutorial:
- Terraform OCI Provider Documentation
- Official OCI Terraform Documentation
- Terraform Registry – OCI Modules (Reusable Terraform configuration)