DEV Community

sys-ronin
sys-ronin

Posted on

Complete OCI Free Tier Infrastructure Guide - Part 01: Setup & Local Provider Mirror

Setting up Oracle Cloud Infrastructure (OCI) using Terraform gives you an automated, reproducible "Always Free" cloud environment. However, managing backend state safely and dealing with air-gapped or restricted provider installations can introduce friction.

In Part 01 of this series, we walk through configuring local credentials, OCI API integration, an S3-compatible backend for state management, an air-gapped local Terraform provider mirror, and a modular folder structure.


Prerequisites

  • A local Linux machine (Debian/Ubuntu preferred) or WSL environment.
  • An active Oracle Cloud Infrastructure (OCI) Free Tier account.
  • OpenSSL, SSH, and Terraform installed.

Phase 1: Local Machine Setup

Generate local cryptographic keys required for SSH access to your instances and secure API authentication with OCI.

1.1 Generate SSH Key Pair (ED25519)

Generate a high-security ED25519 key pair without a passphrase for non-interactive infrastructure management:

ssh-keygen -t ed25519 -N "" -C "oci_vm_key" -f ~/.ssh/oci_vm_key
Enter fullscreen mode Exit fullscreen mode

This generates two files:

  • Private key: ~/.ssh/oci_vm_key (keep safe)
  • Public key: ~/.ssh/oci_vm_key.pub

1.2 Create OCI API Key Directory

Restrict permissions on the configuration directory to preserve security standards:

mkdir -p ~/.oci
chmod 700 ~/.oci
Enter fullscreen mode Exit fullscreen mode

1.3 Generate OCI API Key Pair (RSA 4096)

OCI requires an RSA 4096-bit key pair for programmatic API authentication:

# Generate private key
openssl genrsa -out ~/.oci/oci.pem 4096

# Generate public key
openssl rsa -pubout -in ~/.oci/oci.pem -out ~/.oci/oci_public.pem

# Secure permissions (OCI rejects keys with permissions broader than 600)
chmod 600 ~/.oci/oci.pem
Enter fullscreen mode Exit fullscreen mode

1.4 Generate Key Fingerprint

Extract the MD5 fingerprint of your public key. You will need this to verify API connectivity in the OCI Console:

openssl rsa -pubout -in ~/.oci/oci.pem -outform DER | openssl md5 -c
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Output Example:

MD5(stdin)= 57:0d:ea:8c:07:11:22:33:44:55:66:77:88:99:aa:bb


Phase 2: OCI Console Configuration

2.1 Upload API Public Key

  1. Log into your OCI Console.
  2. Navigate to Profile (top right icon) β†’ My Profile.
  3. Under Resources (bottom left), click API Keys β†’ Add API Key.
  4. Select Paste a Public Key.
  5. Output the contents of ~/.oci/oci_public.pem and paste them into the text box:
   cat ~/.oci/oci_public.pem
Enter fullscreen mode Exit fullscreen mode
  1. Click Add.

πŸ”’ Save Configuration Details:

A Configuration File Preview popup will appear. Copy these valuesβ€”they contain your user OCID, tenancy OCID, fingerprint, and your home region (e.g., ap-hyderabad-1).

2.2 Retrieve Object Storage Namespace

Your Object Storage namespace is a unique, system-generated string tied to your tenant. Retrieve it using the OCI CLI or Cloud Shell:

oci os ns get
Enter fullscreen mode Exit fullscreen mode

Expected JSON output:

{
  "data": "axjetxazylvl"
}
Enter fullscreen mode Exit fullscreen mode

2.3 Create the Terraform Remote State Bucket

Store your .tfstate files remotely in OCI Object Storage:

  1. Open Object Storage β†’ Buckets in the OCI Console.
  2. Click Create Bucket.
  3. Fill in the parameters:
    • Bucket Name: terraform-states
    • Default Storage Tier: Standard
    • Visibility: Private
    • Region: Select your Home Region
  4. Click Create.

2.4 Generate S3-Compatible Credentials

OCI Object Storage provides an S3-compatible API endpoint, allowing you to use standard S3 backend configurations in Terraform.

  1. Go to Profile β†’ My Profile β†’ Customer Secret Keys.
  2. Click Generate Secret Key.
  3. Enter a display name: terraform-backend.
  4. Click Generate Secret Key.

⚠️ Important: Copy and save the generated Secret Key immediately. It will never be displayed again.

  • Access Key: Visible in the Customer Secret Keys table (e.g., f4068126c6fd14c08a121d17396u317e6144e6a2)
  • Secret Key: Copied from the modal dialog.

Phase 3: Shell Environment Setup (~/.bashrc)

To prevent hardcoding sensitive credentials inside your Terraform code, export them as environment variables.

Add the following block to the bottom of your ~/.bashrc file (replace placeholders with your actual OCIDs, keys, and paths):

# =============================================================================
# OCI Provider Credentials
# =============================================================================
export TF_VAR_tenancy_ocid="ocid1.tenancy.oc1..aaaaaaaa..."
export TF_VAR_user_ocid="ocid1.user.oc1..aaaaaaaa..."
export TF_VAR_fingerprint="57:0d:ea:8c:07:..."
export TF_VAR_private_key_path="$HOME/.oci/oci.pem"
export TF_VAR_region="ap-hyderabad-1"
export TF_VAR_compartment_id="ocid1.tenancy.oc1..aaaaaaaa..."

# =============================================================================
# S3-Compatible Backend Credentials (OCI Object Storage S3 API)
# =============================================================================
export AWS_ACCESS_KEY_ID="f4068126c6..."
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY_HERE"
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required

# =============================================================================
# Backend Configuration Variables
# =============================================================================
export TF_VAR_backend_bucket="terraform-states"
export TF_VAR_backend_namespace="axjetxazylvl"
export TF_VAR_backend_region="ap-hyderabad-1"

# =============================================================================
# SSH Key for VM Provisioning
# =============================================================================
export TF_VAR_ssh_public_key_path="$HOME/.ssh/oci_vm_key.pub"

# =============================================================================
# OCI CLI Path & Autocomplete (Adjust path to your user home)
# =============================================================================
export PATH="$HOME/bin:$PATH"
if [[ -f "$HOME/lib/oracle-cli/lib/python3.13/site-packages/oci_cli/bin/oci_autocomplete.sh" ]]; then
  source "$HOME/lib/oracle-cli/lib/python3.13/site-packages/oci_cli/bin/oci_autocomplete.sh"
fi
Enter fullscreen mode Exit fullscreen mode

Apply the environment changes:

source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Phase 4: Offline / Local Provider Mirror Configuration

If you want fast execution or operate in an environment with limited internet access, you can mirror the official OCI provider locally.

4.1 Create Directory Structure

Build the target plugin directory structure expected by Terraform for oracle/oci version 6.20.0:

mkdir -p ~/.terraform.d/plugins-local/registry.terraform.io/oracle/oci/6.20.0/linux_amd64
Enter fullscreen mode Exit fullscreen mode

4.2 Download and Unpack Provider Binary

Download terraform-provider-oci_6.20.0_linux_amd64.zip directly from the HashiCorp or Oracle releases registry, place it in the created path, and unpack it:

cd ~/.terraform.d/plugins-local/registry.terraform.io/oracle/oci/6.20.0/linux_amd64

# Unzip binary package
unzip terraform-provider-oci_6.20.0_linux_amd64.zip

# Rename provider binary to append protocol version target
mv terraform-provider-oci_v6.20.0 terraform-provider-oci_v6.20.0_x5

# Clean up archive
rm terraform-provider-oci_6.20.0_linux_amd64.zip
Enter fullscreen mode Exit fullscreen mode

Verify that your local mirror directory tree matches this structure:

~/.terraform.d/
└── plugins-local
    └── registry.terraform.io
        └── oracle
            └── oci
                └── 6.20.0
                    └── linux_amd64
                        └── terraform-provider-oci_v6.20.0_x5
Enter fullscreen mode Exit fullscreen mode

4.3 Configure Global Provider Installation (~/.terraformrc)

Create a global CLI configuration file at ~/.terraformrc to force Terraform to load the OCI provider directly from your filesystem mirror instead of downloading it during terraform init:

provider_installation {
  filesystem_mirror {
    path    = "/home/YOUR_USER_NAME/.terraform.d/plugins-local"
    include = ["registry.terraform.io/oracle/oci"]
  }
  direct {
    exclude = ["registry.terraform.io/oracle/oci"]
  }
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Note: Replace /home/YOUR_USER_NAME/ with the absolute path to your home directory (Terraform does not expand ~ inside .terraformrc).


Phase 5: Project Directory Architecture

To manage networking and compute instances independently without creating monolithic state files, isolate components into modular subdirectories:

Create the workspace structure:

mkdir -p ~/oci-infra/{shared,vm-amd,vm-arm}
Enter fullscreen mode Exit fullscreen mode
~/oci-infra/
β”œβ”€β”€ shared/          # VCN, subnets, IGW, route tables, security lists, buckets
β”‚   β”œβ”€β”€ backend.tf
β”‚   β”œβ”€β”€ provider.tf
β”‚   β”œβ”€β”€ variables.tf
β”‚   β”œβ”€β”€ main.tf
β”‚   └── outputs.tf
β”œβ”€β”€ vm-amd/          # Always Free x86 Instance (E2.1.Micro + Oracle Linux 9)
β”‚   β”œβ”€β”€ backend.tf
β”‚   β”œβ”€β”€ provider.tf
β”‚   β”œβ”€β”€ variables.tf
β”‚   β”œβ”€β”€ data.tf
β”‚   β”œβ”€β”€ main.tf
β”‚   └── outputs.tf
└── vm-arm/          # Always Free ARM Instance (A1.Flex + Oracle Linux 9)
    β”œβ”€β”€ backend.tf
    β”œβ”€β”€ provider.tf
    β”œβ”€β”€ variables.tf
    β”œβ”€β”€ data.tf
    β”œβ”€β”€ main.tf
    └── outputs.tf
Enter fullscreen mode Exit fullscreen mode

Next Steps

With your API keys generated, environment variables configured, local provider mirrored, and project folders structured, your system is ready.

In Part 02, we will write the HCL declarations for the shared/ moduleβ€”building a Virtual Cloud Network (VCN), public subnets, internet gateways, and locking down security lists within OCI Always Free limits.

Top comments (0)