Skip to main content

Command Palette

Search for a command to run...

Creating an Oracle Cloud VCN with Terraform

Updated
4 min read
Creating an Oracle Cloud VCN with Terraform

A Virtual Cloud Network (VCN) in Oracle Cloud Infrastructure (OCI) is a customizable, software-defined network that hosts your cloud resources such as compute instances, databases, and load balancers.

Using Terraform, you can automate the creation and management of VCNs, ensuring repeatable and consistent infrastructure deployments.

Prerequisites

Before you begin, make sure you have:

  1. OCI Account with permissions to create networking resources.

  2. Terraform installed (v1.10.0 or higher recommended).

  3. OCI Terraform Provider configured.

  4. Your OCI credentials:

    • Tenancy OCID

    • User OCID

    • Compartment OCID

    • Fingerprint

    • Private key path

    • Region

Project Structure

Create a working directory, for example:

oci-vcn-terraform/
│
├── main.tf
├── variables.tf
└── terraform.tfvars

Step 1: Define Provider and Resources (main.tf)

# -------------------------------
# Provider
# -------------------------------
provider "oci" {
  tenancy_ocid     = var.tenancy_ocid
  user_ocid        = var.user_ocid
  fingerprint      = var.fingerprint
  private_key_path = var.private_key_path
  region           = var.region
}

# -------------------------------
# VCN
# -------------------------------
resource "oci_core_vcn" "oke_vcn" {
  cidr_block     = var.vcn_cidr
  compartment_id = var.compartment_ocid
  display_name   = "OKE-VCN-Sydney"
  dns_label      = "okevcn"
}

# -------------------------------
# Gateways
# -------------------------------
resource "oci_core_internet_gateway" "igw" {
  display_name   = "Internet-Gateway"
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.oke_vcn.id
  enabled        = true
}

resource "oci_core_nat_gateway" "nat_gw" {
  display_name   = "NAT-Gateway"
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.oke_vcn.id
  block_traffic  = false
}

# -------------------------------
# Subnet Definitions
# -------------------------------
locals {
  subnets = {
    jump_host = { name = "Jump-Host-Subnet", cidr = var.jump_host_cidr, public = true }
    master    = { name = "Master-Subnet", cidr = var.master_cidr, public = false }
    node      = { name = "Node-Subnet", cidr = var.node_cidr, public = false }
    lb        = { name = "LB-Subnet", cidr = var.lb_cidr, public = true }
    pod       = { name = "POD-Subnet", cidr = var.pod_cidr, public = false }
  }
}

# -------------------------------
# Security Lists
# -------------------------------
resource "oci_core_security_list" "sl" {
  for_each = local.subnets

  display_name   = "Security List for ${each.value.name}"
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.oke_vcn.id

  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "all"
  }

  ingress_security_rules {
    source   = "0.0.0.0/0"
    protocol = "all"
  }
}

# -------------------------------
# Route Tables
# -------------------------------
resource "oci_core_route_table" "rt" {
  for_each = local.subnets

  display_name   = "Route Table for ${each.value.name}"
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.oke_vcn.id

  # Attach Internet Gateway for public subnets
  # Attach NAT Gateway for private subnets
  route_rules {
    description       = each.value.public ? "Route to Internet via IGW" : "Route to Internet via NAT"
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = each.value.public ? oci_core_internet_gateway.igw.id : oci_core_nat_gateway.nat_gw.id
  }
}

# -------------------------------
# Subnets
# -------------------------------
resource "oci_core_subnet" "subnet" {
  for_each = local.subnets

  cidr_block                 = each.value.cidr
  display_name               = each.value.name
  dns_label                  = replace(lower(each.key), "_", "")
  prohibit_public_ip_on_vnic = each.value.public ? false : true
  vcn_id                     = oci_core_vcn.oke_vcn.id
  route_table_id             = oci_core_route_table.rt[each.key].id
  security_list_ids          = [oci_core_security_list.sl[each.key].id]
  compartment_id             = var.compartment_ocid
}

Step 2: Define Variables (variables.tf)

variable "tenancy_ocid" {
  type        = string
  description = "Tenancy OCID"
}

variable "user_ocid" {
  type        = string
  description = "User OCID"
}

variable "fingerprint" {
  type        = string
  description = "API Key Fingerprint"
}

variable "private_key_path" {
  type        = string
  description = "Path to private key"
}

variable "region" {
  type        = string
  description = "OCI region"
}

variable "compartment_ocid" {
  type        = string
  description = "Compartment OCID"
}

variable "existing_vcn_id" {
  type        = string
  description = "Existing VCN OCID"
}

variable "endpoint_subnet_id" {
  type        = string
  description = "Subnet OCID for cluster endpoints"
}

variable "lb_subnet_id" {
  type        = string
  description = "Subnet OCID for load balancer"
}

variable "node_pool_subnet_id" {
  type        = string
  description = "Subnet OCID for node pool"
}

variable "node_pool_ssh_public_key" {
  type        = string
  description = "SSH public key for node pool"
}

variable "nodepool_image_id" {
  type        = string
  description = "OCID of the image for node pool"
}

variable "nodepool_cloud_init" {
  type        = string
  description = "Cloud-init script for node pool"
  default     = ""
}

Step 3: Provide Variable Values (terraform.tfvars)

# -------------------------------
# Provider Authentication
# -------------------------------
tenancy_ocid     = "ocid1.tenancy.oc1.xxx"
user_ocid        = "ocid1.user.oc1..axxx"
fingerprint      = "3a:ds.xx.xx"
private_key_path = "path of key"
region           = "ap-sydney-1"

# -------------------------------
# Networking Details
# -------------------------------
compartment_ocid = "ocid1.compartment.oc1.."

Step 4: Initialize and Apply

terraform init
terraform plan
terraform apply

TerraformConfirm with yes when prompted.
Terraform will provision

| Resource Type    | Count | Purpose                          |
| ---------------- | ----- | -------------------------------- |
| VCN              | 1     | Core network                     |
| Internet Gateway | 1     | Public internet access           |
| NAT Gateway      | 1     | Private outbound internet access |
| Security Lists   | 5     | One per subnet                   |
| Route Tables     | 5     | One per subnet                   |
| Subnets          | 5     | Logical network segments         |

Verification

After the deployment:

  1. Log in to the OCI Console.

  2. Navigate to Networking → Virtual Cloud Networks.

  3. You’ll see the newly created OKE-VCN-Sydney and related resources.

You can also verify via CLI:

oci network vcn list --compartment-id <compartment_ocid>

Clean Up

To remove all resources:

terraform destroy

More from this blog

P

Pratik N Borkar's blog

12 posts