# 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:

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

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

```plaintext
# -------------------------------
# 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`)

```plaintext
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`)

```plaintext
# -------------------------------
# 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

```plaintext
terraform init
terraform plan
terraform apply
```

TerraformConfirm with `yes` when prompted.  
Terraform will provision

```plaintext
| 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:

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

## Clean Up

To remove all resources:

```plaintext
terraform destroy
```
