Skip to main content

Command Palette

Search for a command to run...

Automate OCI Object Storage with Terraform

Updated
5 min read
Automate OCI Object Storage with Terraform
P

I’m Pratik Borkar, a Technical Architecture specializing in Oracle Cloud Infrastructure (OCI) and Kubernetes. I have extensive experience designing, automating, and optimizing cloud environments using Terraform, CI/CD pipelines, and container orchestration tools. I enjoy sharing hands-on guides and real-world implementations that help engineers simplify cloud operations, improve scalability, and adopt Infrastructure as Code best practices. When I’m not automating infrastructure, I explore new DevOps tools, contribute to open-source projects, and write about cloud-native technologies.

Object Storage in Oracle Cloud Infrastructure (OCI) provides durable and scalable storage for any type of data. Using Terraform, we can declaratively create and manage Object Storage Buckets, including lifecycle rules for intelligent data management — such as moving old files to Infrequent Access, Archiving, or Deleting them after a certain time.

In this article, we’ll create:

  • Single Bucket without lifecycle

  • Single Bucket with lifecycle rules

  • Multiple Buckets using a Terraform loop

Prerequisites

Before you begin, make sure you have:

  • An OCI tenancy with Object Storage access

  • Compartment OCID

  • Terraform ≥ 1.5

  • OCI provider ≥ 7.3.0

  • Configured OCI CLI or API keys

1. Single Bucket Without Lifecycle

(main.tf)

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
}

resource "oci_objectstorage_bucket" "bucket" {
  compartment_id = var.compartment_ocid
  name           = var.bucket_name
  namespace      = var.namespace
  storage_tier   = var.storage_tier
}

Define Variables (variables.tf)

variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "region" {}

variable "compartment_ocid" {}
variable "bucket_name" {}
variable "namespace" {}
variable "storage_tier" {
  default = "Standard" # Options: Standard or Archive
}

Provide Variable Values (terraform.tfvars)

private_key_path = "C:/Users/Pratik N Borkar/.oci/xxxx.pem"
user_ocid        = "ocid1.user.oc1..aaaaabmza"
fingerprint      = "3a:d9f:71"
tenancy_ocid     = "ocid1.tenancy.ookmjm7dq"
region           = "ap-sydney-1"


compartment_ocid  = "ocid1.compartr2vdqa"
bucket_name      = "example-bucket"
namespace        = "XXXXXXX"

2. Multiple Bucket Without Lifecycle

(main.tf)

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
}

data "oci_objectstorage_namespace" "ns" {
  compartment_id = var.compartment_ocid
}

locals {
  bucket_names = [for i in range(1, var.bucket_count + 1) : format("AIS-%03d", i)]
}

resource "oci_objectstorage_bucket" "bucket" {
  for_each = toset(local.bucket_names)

  compartment_id     = var.compartment_ocid
  name               = each.value
  namespace          = data.oci_objectstorage_namespace.ns.namespace
  storage_tier       = var.storage_tier
}

Define Variables (variables.tf)

variable "tenancy_ocid" {
  type = string
}

variable "user_ocid" {
  type = string
}

variable "fingerprint" {
  type = string
}

variable "private_key_path" {
  type = string
}

variable "region" {
  type = string
}

variable "compartment_ocid" {
  type = string
}

variable "storage_tier" {
  type    = string
  default = "Standard"
}

variable "bucket_count" {
  type    = number
  default = 10
}

Provide Variable Values (terraform.tfvars)

private_key_path = "C:/Users/Pratik N Borkar/.oci/xxxx.pem"
user_ocid        = "ocid1.user.oc1..aaaaabmza"
fingerprint      = "3a:d9f:71"
tenancy_ocid     = "ocid1.tenancy.ookmjm7dqxxxxxx"
region           = "ap-sydney-1"


compartment_ocid  = "ocid1.compartr2vdqaxxxxx"
storage_tier     = "Standard"
bucket_count     = 10

3. Single Bucket With Lifecycle

(main.tf)

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
}

resource "oci_objectstorage_bucket" "this" {
  count          = var.object_storage_bucket_deploy ? 1 : 0
  compartment_id = var.object_storage_bucket_compartment_ocid
  name           = var.object_storage_bucket_name
  namespace      = var.object_storage_bucket_namespace

  access_type           = "NoPublicAccess"
  auto_tiering          = var.object_storage_bucket_storage_tier == "Standard" ? "Disabled" : null
  metadata              = var.object_storage_bucket_metadata
  freeform_tags         = var.object_storage_bucket_freeform_tags
  object_events_enabled = var.object_storage_bucket_object_events_enabled
  storage_tier          = var.object_storage_bucket_storage_tier
  versioning            = var.object_storage_bucket_versioning
}

resource "oci_objectstorage_object_lifecycle_policy" "this" {
  count     = length(var.object_storage_bucket_lifecycle_policy_rules) == 0 ? 0 : 1
  bucket    = oci_objectstorage_bucket.this[0].name
  namespace = oci_objectstorage_bucket.this[0].namespace

  dynamic "rules" {
    for_each = var.object_storage_bucket_lifecycle_policy_rules
    content {
      action      = rules.value.action
      is_enabled  = rules.value.is_enabled
      name        = rules.value.name
      time_amount = rules.value.time_amount
      time_unit   = rules.value.time_unit
      target      = rules.value.target

      dynamic "object_name_filter" {
        for_each = (
          length(rules.value.object_name_filter.inclusion_patterns) > 0 ||
          length(rules.value.object_name_filter.exclusion_patterns) > 0 ||
          length(rules.value.object_name_filter.inclusion_prefixes) > 0
        ) ? [1] : []

        content {
          exclusion_patterns = toset(rules.value.object_name_filter.exclusion_patterns)
          inclusion_patterns = toset(rules.value.object_name_filter.inclusion_patterns)
          inclusion_prefixes = toset(rules.value.object_name_filter.inclusion_prefixes)
        }
      }
    }
  }
}

resource "oci_objectstorage_object_lifecycle_policy" "multipart_uploads" {
  bucket    = oci_objectstorage_bucket.this[0].name
  namespace = oci_objectstorage_bucket.this[0].namespace

  rules {
    action      = "ABORT"
    is_enabled  = true
    name        = "Delete uncommitted or failed multipart uploads Rule"
    time_amount = "7"
    time_unit   = "DAYS"
    target      = "multipart-uploads"
  }
}

Define Variables (variables.tf)

variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "region" {}

variable "object_storage_bucket_compartment_ocid" {}
variable "object_storage_bucket_name" {}
variable "object_storage_bucket_namespace" {}

variable "object_storage_bucket_metadata" {
  type = map(string)
  default = {}
}

variable "object_storage_bucket_freeform_tags" {
  type = map(string)
  default = {}
}

variable "object_storage_bucket_object_events_enabled" {
  type    = bool
  default = false
}

variable "object_storage_bucket_versioning" {
  default = "Enabled"
}

variable "object_storage_bucket_storage_tier" {
  default = "Standard"
}

variable "object_storage_bucket_deploy" {
  type    = bool
  default = true
}

variable "object_storage_bucket_lifecycle_policy_rules" {
  type = list(object({
    action      = string
    is_enabled  = bool
    name        = string
    time_amount = number
    time_unit   = string
    target      = string
    object_name_filter = object({
      inclusion_patterns = list(string)
      exclusion_patterns = list(string)
      inclusion_prefixes = list(string)
    })
  }))
}

Provide Variable Values (terraform.tfvars)

private_key_path = "C:/Users/Pratik N Borkar/.oci/xxxx.pem"
user_ocid        = "ocid1.user.oc1..aaaaabmza"
fingerprint      = "3a:d9f:71"
tenancy_ocid     = "ocid1.tenancy.ookmjm7dqxxxxxx"
region           = "ap-sydney-1"


object_storage_bucket_compartment_ocid = "ocid1.compartmei3ier2vdqa"
object_storage_bucket_name             = "my-logs-bucket"
object_storage_bucket_namespace        = "XXXXXXX"

object_storage_bucket_metadata = {}
object_storage_bucket_freeform_tags = {
  Environment = "Dev"
}
object_storage_bucket_object_events_enabled = false
object_storage_bucket_versioning            = "Enabled"
object_storage_bucket_storage_tier          = "Standard"

object_storage_bucket_lifecycle_policy_rules = [
  {
    action      = "INFREQUENT_ACCESS"
    is_enabled  = true
    name        = "Move Infrequent Access Objects Rule"
    time_amount = 45
    time_unit   = "DAYS"
    target      = "objects"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  },
  {
    action      = "ARCHIVE"
    is_enabled  = true
    name        = "Archive Objects Rule"
    time_amount = 90
    time_unit   = "DAYS"
    target      = "objects"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  },
  {
    action      = "DELETE"
    is_enabled  = true
    name        = "Delete Objects Rule"
    time_amount = 120
    time_unit   = "DAYS"
    target      = "objects"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  },
  {
    action      = "INFREQUENT_ACCESS"
    is_enabled  = true
    name        = "Move Infrequent Access Previous Versions Rule"
    time_amount = 45
    time_unit   = "DAYS"
    target      = "previous-object-versions"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  },
  {
    action      = "ARCHIVE"
    is_enabled  = true
    name        = "Archive Previous Versions Rule"
    time_amount = 90
    time_unit   = "DAYS"
    target      = "previous-object-versions"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  },
  {
    action      = "DELETE"
    is_enabled  = true
    name        = "Delete Previous Versions Rule"
    time_amount = 240
    time_unit   = "DAYS"
    target      = "previous-object-versions"
    object_name_filter = {
      inclusion_patterns = []
      exclusion_patterns = []
      inclusion_prefixes = []
    }
  }
]

Summary

FolderDescription
Single-Without-LifecycleCreates a single basic Object Storage bucket
Single-With-LifecycleAdds 6 lifecycle rules for object and version management
Multiple BucketCreates multiple buckets dynamically using Terraform loops

More from this blog

P

Pratik N Borkar's blog

13 posts