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
}
-
Terraform Engine: Requires version
>= 1.5.0[cite: 5]. -
OCI Provider: Pins the
oracle/ociprovider to version6.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
}
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
}
}
-
Bucket & State Key: Stores the state in
terraform-statesundershared.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"
}
Resource Breakdown
-
VCN (
oci_core_vcn.main): Namedmain-vcnwith CIDR10.0.0.0/16and internal DNS labelmainvcn[cite: 3]. -
Internet Gateway (
oci_core_internet_gateway.main): Namedmain-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].
- TCP port 22 (SSH) allowed from anywhere (
-
Public Subnet (
oci_core_subnet.public): CIDR block10.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): Namedinfra-data, using namespaceaxjetxazylvl, standard storage tier, andNoPublicAccess[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"
}
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
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)