DEV Community

sys-ronin
sys-ronin

Posted on

Complete OCI Free Tier Infrastructure Guide - Part 02: Shared Architecture Layer

In Part 01 of this guide, we configured local keys, exported shell variables, created an offline provider mirror, and established our remote state bucket.

Now in Part 02, we build the foundation of our cloud environment in ~/oci-infra/shared/. This shared architecture layer provisions the core Virtual Cloud Network (VCN), internet gateway, public subnet, security rules, standard Object Storage bucket, and S3-compatible remote state backend configuration [cite: 2, 3].


1. Provider Configuration (provider.tf)

Defines the required Terraform engine and provider versions [cite: 5], along with authentication credentials passed via shell environment variables [cite: 5, 6].

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    oci = {
      source  = "oracle/oci"
      version = "6.20.0"
    }
  }
}

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
}
Enter fullscreen mode Exit fullscreen mode
  • Terraform Engine: Requires version >= 1.5.0 [cite: 5].
  • OCI Provider: Pins the oracle/oci provider to version 6.20.0 [cite: 5].
  • Authentication: Uses API key configuration via tenancy OCID, user OCID, fingerprint, private key path, and region [cite: 5].

2. Environment Variables (variables.tf)

Defines the required input variables used to configure authentication and resource placement [cite: 6].

variable "tenancy_ocid" {
  description = "OCID of the tenancy"
  type        = string
}

variable "user_ocid" {
  description = "OCID of the user"
  type        = string
}

variable "fingerprint" {
  description = "API key fingerprint"
  type        = string
}

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

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

variable "compartment_id" {
  description = "OCID of the compartment to create resources in"
  type        = string
}
Enter fullscreen mode Exit fullscreen mode

3. Remote State Backend (backend.tf)

Configures Terraform to store state remotely inside an OCI Object Storage bucket using the S3-compatible API [cite: 2].

terraform {
  backend "s3" {
    bucket = "terraform-states"
    key    = "shared.tfstate"
    region = "ap-hyderabad-1"
    endpoints = {
      s3 = "https://axjetxazylvl.compat.objectstorage.ap-hyderabad-1.oraclecloud.com"
    }

    skip_region_validation      = true
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    skip_requesting_account_id  = true
    skip_s3_checksum            = true
    use_path_style              = true
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Bucket & State Key: Stores the state in terraform-states under shared.tfstate [cite: 2].
  • S3 Compatibility Endpoint: Points directly to OCI's native S3 API endpoint (https://axjetxazylvl.compat.objectstorage.ap-hyderabad-1.oraclecloud.com) [cite: 2].
  • AWS S3 Overrides: Forces path-style addressing (use_path_style = true) and disables standard AWS-specific checks (checksums, metadata API, credentials validation) to maintain OCI compatibility [cite: 2].

4. Main Infrastructure Resources (main.tf)

Contains resources for the Virtual Cloud Network (VCN), networking gateway, security list, public subnet, and storage bucket [cite: 3].

# -----------------------------------------------------------------------------
# Virtual Cloud Network
# -----------------------------------------------------------------------------
resource "oci_core_vcn" "main" {
  compartment_id = var.compartment_id
  cidr_block     = "10.0.0.0/16"
  display_name   = "main-vcn"
  dns_label      = "mainvcn"
}

# -----------------------------------------------------------------------------
# Internet Gateway
# -----------------------------------------------------------------------------
resource "oci_core_internet_gateway" "main" {
  compartment_id = var.compartment_id
  vcn_id         = oci_core_vcn.main.id
  display_name   = "main-igw"
}

# -----------------------------------------------------------------------------
# Route Table
# -----------------------------------------------------------------------------
resource "oci_core_route_table" "public" {
  compartment_id = var.compartment_id
  vcn_id         = oci_core_vcn.main.id
  display_name   = "public-route-table"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.main.id
  }
}

# -----------------------------------------------------------------------------
# Security List
# -----------------------------------------------------------------------------
resource "oci_core_security_list" "public" {
  compartment_id = var.compartment_id
  vcn_id         = oci_core_vcn.main.id
  display_name   = "public-security-list"

  # SSH from anywhere
  ingress_security_rules {
    protocol    = "6" # TCP
    source      = "0.0.0.0/0"
    source_type = "CIDR_BLOCK"
    tcp_options {
      min = 22
      max = 22
    }
  }

  # ICMP for MTU path discovery (required by OCI)
  ingress_security_rules {
    protocol    = "1" # ICMP
    source      = "0.0.0.0/0"
    source_type = "CIDR_BLOCK"
    icmp_options {
      type = 3
      code = 4
    }
  }

  # Allow ping (ICMP echo request/reply)
  ingress_security_rules {
    protocol    = "1" # ICMP
    source      = "0.0.0.0/0"
    source_type = "CIDR_BLOCK"
    icmp_options {
      type = 8  # Echo Request
      code = -1 # All codes
    }
  }

  # Allow all outbound
  egress_security_rules {
    protocol    = "all"
    destination = "0.0.0.0/0"
  }
}

# -----------------------------------------------------------------------------
# Subnet
# -----------------------------------------------------------------------------
resource "oci_core_subnet" "public" {
  compartment_id             = var.compartment_id
  vcn_id                     = oci_core_vcn.main.id
  cidr_block                 = "10.0.0.0/24"
  display_name               = "shared-public-subnet"
  dns_label                  = "public"
  route_table_id             = oci_core_route_table.public.id
  security_list_ids          = [oci_core_security_list.public.id]
  prohibit_public_ip_on_vnic = false
}

# -----------------------------------------------------------------------------
# Object Storage Bucket
# -----------------------------------------------------------------------------
resource "oci_objectstorage_bucket" "infra_data" {
  compartment_id = var.compartment_id
  namespace      = "axjetxazylvl"
  name           = "infra-data"
  storage_tier   = "Standard"
  access_type    = "NoPublicAccess"
}
Enter fullscreen mode Exit fullscreen mode

Resource Breakdown

  • VCN (oci_core_vcn.main): Named main-vcn with CIDR 10.0.0.0/16 and internal DNS label mainvcn [cite: 3].
  • Internet Gateway (oci_core_internet_gateway.main): Named main-igw, allowing outbound internet connection for instances [cite: 3].
  • Route Table (oci_core_route_table.public): Directs default outbound traffic (0.0.0.0/0) through the Internet Gateway [cite: 3].
  • Security List (oci_core_security_list.public):
    • TCP port 22 (SSH) allowed from anywhere (0.0.0.0/0) [cite: 3].
    • ICMP Type 3 Code 4 enabled (required by OCI for path MTU discovery) [cite: 3].
    • ICMP Type 8 (Echo Request / Ping) enabled [cite: 3].
    • Full egress traffic (0.0.0.0/0) allowed [cite: 3].
  • Public Subnet (oci_core_subnet.public): CIDR block 10.0.0.0/24, attached to the public route table and public security list, with public IPs allowed (prohibit_public_ip_on_vnic = false) [cite: 3].
  • Object Storage Bucket (oci_objectstorage_bucket.infra_data): Named infra-data, using namespace axjetxazylvl, standard storage tier, and NoPublicAccess [cite: 3].

5. Architectural Outputs (outputs.tf)

Exposes critical resource IDs and attributes for reference by isolated sub-modules (such as compute instances) [cite: 4].

output "vcn_id" {
  description = "OCID of the created VCN"
  value       = oci_core_vcn.main.id
}

output "vcn_cidr" {
  description = "CIDR block of the VCN"
  value       = oci_core_vcn.main.cidr_block
}

output "vcn_dns_label" {
  description = "DNS label of the VCN"
  value       = oci_core_vcn.main.dns_label
}

output "subnet_id" {
  description = "OCID of the public subnet"
  value       = oci_core_subnet.public.id
}

output "subnet_cidr" {
  description = "CIDR block of the public subnet"
  value       = oci_core_subnet.public.cidr_block
}

output "subnet_dns_label" {
  description = "DNS label of the public subnet"
  value       = oci_core_subnet.public.dns_label
}

output "internet_gateway_id" {
  description = "OCID of the Internet Gateway"
  value       = oci_core_internet_gateway.main.id
}

output "security_list_id" {
  description = "OCID of the Security List"
  value       = oci_core_security_list.public.id
}

output "infra_bucket_name" {
  description = "Name of the application bucket"
  value       = oci_objectstorage_bucket.infra_data.name
}

output "infra_bucket_namespace" {
  description = "Namespace of the application bucket"
  value       = oci_objectstorage_bucket.infra_data.namespace
}

output "infra_bucket_endpoint" {
  description = "S3-compatible endpoint for the application bucket"
  value       = "https://${oci_objectstorage_bucket.infra_data.namespace}.compat.objectstorage.${var.region}.oraclecloud.com"
}
Enter fullscreen mode Exit fullscreen mode

6. Execution Workflow

From inside the ~/oci-infra/shared/ directory, run:

# Initialize using the local provider mirror and remote S3 state backend
terraform init

# Review execution plan
terraform plan

# Apply infrastructure changes
terraform apply
Enter fullscreen mode Exit fullscreen mode

Next Steps

With your shared core networking, security rules, and state storage provisioned, your tenancy foundation is complete.

In Part 03, we will provision the compute layer—deploying Always Free x86 (vm-amd) and ARM Ampere (vm-arm) instances connected directly to shared-public-subnet.

Top comments (0)